Name: viR10068 Date: 10/31/2003
The spec for RegisterNatives() method say:
"RETURNS:
Returns "0" on success; returns a negative value on failure."
But the jdk1.5-b26 returns '0' if the method throws NoSuchMethodError.
Note, the jdk1.5-b25 returns a negative value.
The JCK test
vm/jni/RegisterNatives/rgnt001/rgnt00103m1/rgnt00103m1.html
failed due to this bug.
The example:
-------------------------- rgnt00103m1.java ------------------------
package javasoft.sqe.tests.vm.jni.rgnt001.rgnt00103m1;
import java.io.PrintStream;
public class rgnt00103m1 {
void nm() {
}
native void rgnt00103m1RN1();
native int rgnt00103m1RN2();
native void rgnt00103m1RN3();
native int rgnt00103m1RN4();
public static int testChecks(PrintStream out) {
boolean res = false;
rgnt00103m1 tob = new rgnt00103m1();
// NoSuchMethodError: if a specified method cannot be found.
try {
tob.rgnt00103m1RN1();
out.println("NoSuchMethodError expected");
res = true;
} catch (NoSuchMethodError e) {
out.println("Passed with: " + e);
} catch (Throwable e) {
out.println("Exception caught: " + e);
res = true;
}
try {
if (tob.rgnt00103m1RN2() >= 0) {
out.println("Failed: RegisterNatives must return negative value. Return: "
+ tob.rgnt00103m1RN2());
res = true;
}
} catch (Throwable e) {
out.println("Exception caught: "+e);
res = true;
}
// NoSuchMethodError: if a specified method is not native.
try {
tob.rgnt00103m1RN3();
out.println("NoSuchMethodError expected");
res = true;
} catch (NoSuchMethodError e) {
out.println("Passed with: " + e);
} catch (Throwable e) {
out.println("Exception caught: " + e);
res = true;
}
try {
if (tob.rgnt00103m1RN4() >= 0) {
out.println("Failed: RegisterNatives must return negative value. Return: "
+ tob.rgnt00103m1RN4());
res = true;
}
} catch (Throwable e) {
out.println("Exception caught: "+e);
res = true;
}
if (res) {
return 2 /*STATUS_FAILED*/;
}
return 0 /*STATUS_PASSED*/;
}
static String loadLibraryStatus = "";
static {
if(!loadLib("rgnt00103m1")) {
loadLib("jckjni");
}
}
static boolean loadLib(String libName){
try {
System.loadLibrary(libName);
loadLibraryStatus = null;
return true;
} catch (SecurityException e) {
loadLibraryStatus += "loadLibrary(\"" + libName + "\") throws: " + e + "\n";
} catch (UnsatisfiedLinkError e) {
loadLibraryStatus += "loadLibrary(\"" + libName + "\") throws: " + e + "\n";
}
return false;
}
public static int run(String argv[], PrintStream out) {
if (loadLibraryStatus!=null) {
out.println("Library loading:\n" + loadLibraryStatus);
}
return testChecks(out);
}
public static void main(String argv[]) {
System.exit(run(argv, System.out) + 95/*STATUS_TEMP*/);
}
}
-----------------------------------------------------------------
-----------------------rgnt00103m1.c-----------------------------
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "jckjni.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifndef JNI_ENV_ARG
#ifdef __cplusplus
#define JNI_ENV_ARG(x, y) y
#define JNI_ENV_PTR(x) x
#else
#define JNI_ENV_ARG(x,y) x, y
#define JNI_ENV_PTR(x) (*x)
#endif
#endif
#ifdef __cplusplus
#define JNI_EARG(x)
#else
#define JNI_EARG(x) x
#endif
JNIEXPORT void JNICALL rgnt00103m1method(JNIEnv *env, jobject obj) {
return;
}
JNINativeMethod rgnt00103m1JNINMA1[] = { { (char*)"unexist", (char*)"()",
(void*)&rgnt00103m1method } };
JNINativeMethod rgnt00103m1JNINMA2[] = { { (char*)"nm", (char*)"()",
(void*)&rgnt00103m1method } };
JNIEXPORT void JNICALL
Java_javasoft_sqe_tests_vm_jni_rgnt001_rgnt00103m1_rgnt00103m1_rgnt00103m1RN1(
JNIEnv *env, jobject obj) {
jclass jc;
jc = JNI_ENV_PTR(env) -> GetObjectClass(JNI_ENV_ARG(env, obj));
if ( jc == NULL) return;
JNI_ENV_PTR(env)->RegisterNatives(JNI_ENV_ARG(env,jc), rgnt00103m1JNINMA1, 1);
return;
}
JNIEXPORT jint JNICALL
Java_javasoft_sqe_tests_vm_jni_rgnt001_rgnt00103m1_rgnt00103m1_rgnt00103m1RN2(
JNIEnv *env, jobject obj) {
jclass jc;
jint res;
jc = JNI_ENV_PTR(env) -> GetObjectClass(JNI_ENV_ARG(env, obj));
if ( jc == NULL) return;
res = JNI_ENV_PTR(env)->RegisterNatives(JNI_ENV_ARG(env,jc), rgnt00103m1JNINMA1, 1);
JNI_ENV_PTR(env) -> ExceptionClear(JNI_EARG(env));
return res;
}
JNIEXPORT void JNICALL
Java_javasoft_sqe_tests_vm_jni_rgnt001_rgnt00103m1_rgnt00103m1_rgnt00103m1RN3(
JNIEnv *env, jobject obj) {
jclass jc;
jc = JNI_ENV_PTR(env) -> GetObjectClass(JNI_ENV_ARG(env, obj));
if ( jc == NULL) return;
JNI_ENV_PTR(env)->RegisterNatives(JNI_ENV_ARG(env,jc), rgnt00103m1JNINMA2, 1);
return;
}
JNIEXPORT jint JNICALL
Java_javasoft_sqe_tests_vm_jni_rgnt001_rgnt00103m1_rgnt00103m1_rgnt00103m1RN4(
JNIEnv *env, jobject obj) {
jclass jc;
jint res;
jc = JNI_ENV_PTR(env) -> GetObjectClass(JNI_ENV_ARG(env, obj));
if ( jc == NULL) return;
res = JNI_ENV_PTR(env)->RegisterNatives(JNI_ENV_ARG(env,jc), rgnt00103m1JNINMA2, 1);
JNI_ENV_PTR(env) -> ExceptionClear(JNI_EARG(env));
return res;
}
#ifdef __cplusplus
}
#endif
-----------------------------------------------------------------
The execution log:
% ls include
jckjlong_md.h jckjni.h jckjni_md.h
%javac -d . rgnt00103m1.java && cc -G -KPIC -o libjckjni.so -Iinclude rgnt00103m1.c
%jdk1.5.0-b25/solaris-sparc/bin/java -showversion -Xfuture
javasoft.sqe.tests.vm.jni.rgnt001.rgnt00103m1.rgnt00103m1
java version "1.5.0-beta"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0-beta-b25)
Java HotSpot(TM) Client VM (build 1.5.0-beta-b25, mixed mode)
Passed with: java.lang.NoSuchMethodError:
javasoft.sqe.tests.vm.jni.rgnt001.rgnt00103m1.rgnt00103m1.unexist()
Passed with: java.lang.NoSuchMethodError:
javasoft.sqe.tests.vm.jni.rgnt001.rgnt00103m1.rgnt00103m1.nm()
% jdk1.5.0-b26/solaris-sparc/bin/java -showversion -Xfuture
javasoft.sqe.tests.vm.jni.rgnt001.rgnt00103m1.rgnt00103m1
java version "1.5.0-beta"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0-beta-b26)
Java HotSpot(TM) Client VM (build 1.5.0-beta-b26, mixed mode)
Passed with: java.lang.NoSuchMethodError: unexist
Failed: RegisterNatives must return negative value. Return: 0
Passed with: java.lang.NoSuchMethodError: nm
Failed: RegisterNatives must return negative value. Return: 0
%
======================================================================