hg: jdk7/tl/jdk: 6935563: (dc) Improve connection reset/port unreachable handling [win]
Changeset: af68ad345389 Author:alanb Date: 2010-06-09 18:51 +0100 URL: http://hg.openjdk.java.net/jdk7/tl/jdk/rev/af68ad345389 6935563: (dc) Improve connection reset/port unreachable handling [win] Reviewed-by: chegar ! src/windows/native/sun/nio/ch/DatagramChannelImpl.c ! src/windows/native/sun/nio/ch/Net.c + test/java/nio/channels/DatagramChannel/SelectWhenRefused.java
Re: Must call RegisterNatives after getMethodID, else get UnsatisfiedLinkError
David, Thanks for the bug archaeology. Judging by the other commenters, this bug is a regression from jdk5, and has cost many other users hours of frustrating debugging time, so I think an increase to P2 is in order. Since it used to work, it shouldn't be too hard to fix - all you need to do is to properly track registered native methods. Sorry for not doing this kind of research myself - it's just too painful without my beloved jbugs script :-( Here's an improved version of our test case, with -XX:+PrintJNIResolving output added, that you might add to the bug report. $ cat Test.java; echo -; cat jvm.cc; echo --; JDK=`jver 1.7.0-b96`; g++ -I$JDK/include -I$JDK/include/linux -ldl -DJDK=\"$JDK\" jvm.cc && ./a.out public class Test { public Test() { System.out.println("My class loader is " + getClass().getClassLoader()); testNative(); System.out.println("back to Java"); } public static native void testNative(); } - #include #include #include #include JavaVM* jvm; JNIEnv* env; const char* libjvm = JDK "/jre/lib/amd64/server/libjvm.so"; const char* loader_url = "file://./"; const char* class_name = "Test"; #define countof(array) (sizeof(array)/sizeof(array[0])) void InitializeJVM() { JavaVMOption options[] = { { (char*)"-Djava.class.path=.", NULL }, { (char*)"-XX:+PrintJNIResolving", NULL }, //{ (char*)"-verbose:jni", NULL }, }; JavaVMInitArgs vm_args; vm_args.version = JNI_VERSION_1_2; vm_args.options = options; vm_args.nOptions = countof(options); vm_args.ignoreUnrecognized = JNI_TRUE; void* handle = dlopen(libjvm, RTLD_LAZY); if (!handle) { fprintf(stderr, "%s\n", dlerror()); exit(1); } jint JNICALL (*func_create_java_vm)(JavaVM**, void**, void*) = reinterpret_cast (dlsym(handle, "JNI_CreateJavaVM")); if (!func_create_java_vm) { fprintf(stderr, "%s\n", dlerror()); exit(1); } jint result = (*func_create_java_vm)(&jvm, (void**)(&env), &vm_args); } void TestNative(JNIEnv* env, jclass cls) { printf("Successfully called registered native method\n"); } void RegisterNativeMethod(jclass cls) { static const JNINativeMethod jni_method = { (char*)"testNative", (char*)"()V", (void*)&TestNative }; env->RegisterNatives(cls, &jni_method, 1); if (env->ExceptionCheck()) env->ExceptionDescribe(); } void Test() { // URL[] urls = {new URL(url)} jclass cls = env->FindClass("java/net/URL"); jmethodID method = env->GetMethodID(cls, "", "(Ljava/lang/String;)V"); jstring jurl_str = env->NewStringUTF(loader_url); jobject jurl = env->NewObject(cls, method, jurl_str); jobjectArray jurls = env->NewObjectArray(1, cls, jurl); // URLClassLoader loader = new URLClassLoaer(urls) cls = env->FindClass("java/net/URLClassLoader"); method = env->GetMethodID(cls, "", "([Ljava/net/URL;)V"); jobject jloader = env->NewObject(cls, method, jurls); // Class cls = loader.loadClass(name) method = env->GetMethodID( cls, "loadClass", "(Ljava/lang/String;Z)Ljava/lang/Class;"); jstring jname = env->NewStringUTF(class_name); cls = (jclass)env->CallObjectMethod(jloader, method, jname, (jboolean) true); // RegisterNatives must be called after GetMethodID. // If the order is reversed, we get UnsatisfiedLinkError, // which seems like a bug. RegisterNativeMethod(cls); method = env->GetMethodID(cls, "", "()V"); if (env->ExceptionCheck()) env->ExceptionDescribe(); env->NewObject(cls, method); if (env->ExceptionCheck()) env->ExceptionDescribe(); } int main(int argc, char** argv) { InitializeJVM(); Test(); return 0; } -- [Dynamic-linking native method java.lang.Object.registerNatives ... JNI] [Registering JNI native method java.lang.Object.hashCode] [Registering JNI native method java.lang.Object.wait] [Registering JNI native method java.lang.Object.notify] [Registering JNI native method java.lang.Object.notifyAll] [Registering JNI native method java.lang.Object.clone] [Dynamic-linking native method java.lang.System.registerNatives ... JNI] [Registering JNI native method java.lang.System.currentTimeMillis] [Registering JNI native method java.lang.System.nanoTime] [Registering JNI native method java.lang.System.arraycopy] [Dynamic-linking native method java.lang.Thread.registerNatives ... JNI] [Registering JNI native method java.lang.Thread.start0] [Registering JNI native method java.lang.Thread.stop0] [Registering JNI native method java.lang.Thread.isAlive] [Registering JNI native method java.lang.Thread.suspend0] [Registering JNI native method java.lang.Thread.resume0] [Registering JNI native method java.lang.Thread.setPriority0] [Registering JNI native method java.lang.Thread.yield] [Registering JNI native method java.lang.Thread.sleep] [Registering JNI native method java.lang.Thread.currentThread] [Registering JNI native method java.lang.Thread.countStackFrames] [Registering JNI native method java.lang.
Re: Must call RegisterNatives after getMethodID, else get UnsatisfiedLinkError
It's been a while since I worked with this stuff, but I would have done a: jclass cls = env->FindClass("Test"); Which, if I recall, FindClass actually initializes the class. Just a stab in the dark. -kto On Jun 9, 2010, at 12:39 PM, Martin Buchholz wrote: David, Thanks for the bug archaeology. Judging by the other commenters, this bug is a regression from jdk5, and has cost many other users hours of frustrating debugging time, so I think an increase to P2 is in order. Since it used to work, it shouldn't be too hard to fix - all you need to do is to properly track registered native methods. Sorry for not doing this kind of research myself - it's just too painful without my beloved jbugs script :-( Here's an improved version of our test case, with -XX:+PrintJNIResolving output added, that you might add to the bug report. $ cat Test.java; echo -; cat jvm.cc; echo --; JDK=`jver 1.7.0-b96`; g++ -I$JDK/include -I$JDK/include/linux -ldl -DJDK=\"$JDK\" jvm.cc && ./a.out public class Test { public Test() { System.out.println("My class loader is " + getClass().getClassLoader()); testNative(); System.out.println("back to Java"); } public static native void testNative(); } - #include #include #include #include JavaVM* jvm; JNIEnv* env; const char* libjvm = JDK "/jre/lib/amd64/server/libjvm.so"; const char* loader_url = "file://./"; const char* class_name = "Test"; #define countof(array) (sizeof(array)/sizeof(array[0])) void InitializeJVM() { JavaVMOption options[] = { { (char*)"-Djava.class.path=.", NULL }, { (char*)"-XX:+PrintJNIResolving", NULL }, //{ (char*)"-verbose:jni", NULL }, }; JavaVMInitArgs vm_args; vm_args.version = JNI_VERSION_1_2; vm_args.options = options; vm_args.nOptions = countof(options); vm_args.ignoreUnrecognized = JNI_TRUE; void* handle = dlopen(libjvm, RTLD_LAZY); if (!handle) { fprintf(stderr, "%s\n", dlerror()); exit(1); } jint JNICALL (*func_create_java_vm)(JavaVM**, void**, void*) = reinterpret_cast (dlsym(handle, "JNI_CreateJavaVM")); if (!func_create_java_vm) { fprintf(stderr, "%s\n", dlerror()); exit(1); } jint result = (*func_create_java_vm)(&jvm, (void**)(&env), &vm_args); } void TestNative(JNIEnv* env, jclass cls) { printf("Successfully called registered native method\n"); } void RegisterNativeMethod(jclass cls) { static const JNINativeMethod jni_method = { (char*)"testNative", (char*)"()V", (void*)&TestNative }; env->RegisterNatives(cls, &jni_method, 1); if (env->ExceptionCheck()) env->ExceptionDescribe(); } void Test() { // URL[] urls = {new URL(url)} jclass cls = env->FindClass("java/net/URL"); jmethodID method = env->GetMethodID(cls, "", "(Ljava/lang/ String;)V"); jstring jurl_str = env->NewStringUTF(loader_url); jobject jurl = env->NewObject(cls, method, jurl_str); jobjectArray jurls = env->NewObjectArray(1, cls, jurl); // URLClassLoader loader = new URLClassLoaer(urls) cls = env->FindClass("java/net/URLClassLoader"); method = env->GetMethodID(cls, "", "([Ljava/net/URL;)V"); jobject jloader = env->NewObject(cls, method, jurls); // Class cls = loader.loadClass(name) method = env->GetMethodID( cls, "loadClass", "(Ljava/lang/String;Z)Ljava/lang/Class;"); jstring jname = env->NewStringUTF(class_name); cls = (jclass)env->CallObjectMethod(jloader, method, jname, (jboolean) true); // RegisterNatives must be called after GetMethodID. // If the order is reversed, we get UnsatisfiedLinkError, // which seems like a bug. RegisterNativeMethod(cls); method = env->GetMethodID(cls, "", "()V"); if (env->ExceptionCheck()) env->ExceptionDescribe(); env->NewObject(cls, method); if (env->ExceptionCheck()) env->ExceptionDescribe(); } int main(int argc, char** argv) { InitializeJVM(); Test(); return 0; } -- [Dynamic-linking native method java.lang.Object.registerNatives ... JNI] [Registering JNI native method java.lang.Object.hashCode] [Registering JNI native method java.lang.Object.wait] [Registering JNI native method java.lang.Object.notify] [Registering JNI native method java.lang.Object.notifyAll] [Registering JNI native method java.lang.Object.clone] [Dynamic-linking native method java.lang.System.registerNatives ... JNI] [Registering JNI native method java.lang.System.currentTimeMillis] [Registering JNI native method java.lang.System.nanoTime] [Registering JNI native method java.lang.System.arraycopy] [Dynamic-linking native method java.lang.Thread.registerNatives ... JNI] [Registering JNI native method java.lang.Thread.start0] [Registering JNI native method java.lang.Thread.stop0] [Registering JNI native method java.lang.Thread.isAlive] [Registering JNI native method java.lang.Thread.suspend0] [Registering JNI native method java.lang.Thread.resume0] [Registering JNI native method java.lang.Thread.setPriority0] [Registering JNI native method java.lang.Threa