Must call RegisterNatives after getMethodID, else get UnsatisfiedLinkError

Kelly O'Hair kelly.ohair at oracle.com
Wed Jun 9 19:52:50 UTC 2010


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 <cstdio>
> #include <cstdlib>
> #include <dlfcn.h>
> #include <jni.h>
>
> 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<jint JNICALL (*)(JavaVM**, void**, void*)>
>      (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, "<init>", "(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, "<init>", "([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, "<init>", "()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.Thread.interrupt0]
> [Registering JNI native method java.lang.Thread.isInterrupted]
> [Registering JNI native method java.lang.Thread.holdsLock]
> [Registering JNI native method java.lang.Thread.getThreads]
> [Registering JNI native method java.lang.Thread.dumpThreads]
> [Dynamic-linking native method
> java.security.AccessController.getStackAccessControlContext ... JNI]
> [Dynamic-linking native method
> java.security.AccessController.getInheritedAccessControlContext ...
> JNI]
> [Dynamic-linking native method  
> java.lang.ClassLoader.registerNatives ... JNI]
> [Registering JNI native method  
> java.lang.ClassLoader.retrieveDirectives]
> [Dynamic-linking native method
> java.security.AccessController.doPrivileged ... JNI]
> [Dynamic-linking native method java.lang.Class.registerNatives ...  
> JNI]
> [Registering JNI native method java.lang.Class.getName0]
> [Registering JNI native method java.lang.Class.getSuperclass]
> [Registering JNI native method java.lang.Class.getInterfaces]
> [Registering JNI native method java.lang.Class.getClassLoader0]
> [Registering JNI native method java.lang.Class.isInterface]
> [Registering JNI native method java.lang.Class.getSigners]
> [Registering JNI native method java.lang.Class.setSigners]
> [Registering JNI native method java.lang.Class.isArray]
> [Registering JNI native method java.lang.Class.isPrimitive]
> [Registering JNI native method java.lang.Class.getComponentType]
> [Registering JNI native method java.lang.Class.getModifiers]
> [Registering JNI native method java.lang.Class.getDeclaredFields0]
> [Registering JNI native method java.lang.Class.getDeclaredMethods0]
> [Registering JNI native method  
> java.lang.Class.getDeclaredConstructors0]
> [Registering JNI native method java.lang.Class.getProtectionDomain0]
> [Registering JNI native method java.lang.Class.setProtectionDomain0]
> [Registering JNI native method java.lang.Class.getDeclaredClasses0]
> [Registering JNI native method java.lang.Class.getDeclaringClass]
> [Registering JNI native method java.lang.Class.getGenericSignature]
> [Registering JNI native method java.lang.Class.getRawAnnotations]
> [Registering JNI native method java.lang.Class.getConstantPool]
> [Registering JNI native method  
> java.lang.Class.desiredAssertionStatus0]
> [Registering JNI native method java.lang.Class.getEnclosingMethod0]
> [Dynamic-linking native method java.lang.Class.getPrimitiveClass ...  
> JNI]
> [Dynamic-linking native method java.lang.System.initProperties ...  
> JNI]
> [Dynamic-linking native method sun.misc.Unsafe.registerNatives ...  
> JNI]
> [Registering JNI native method sun.misc.Unsafe.getLoadAverage]
> [Dynamic-linking native method  
> java.lang.Throwable.fillInStackTrace ... JNI]
> [Registering JNI native method sun.misc.Unsafe.copyMemory]
> [Registering JNI native method sun.misc.Unsafe.setMemory]
> [Registering JNI native method sun.misc.Unsafe.getObject]
> [Registering JNI native method sun.misc.Unsafe.putObject]
> [Registering JNI native method sun.misc.Unsafe.getObjectVolatile]
> [Registering JNI native method sun.misc.Unsafe.putObjectVolatile]
> [Registering JNI native method sun.misc.Unsafe.getBoolean]
> [Registering JNI native method sun.misc.Unsafe.putBoolean]
> [Registering JNI native method sun.misc.Unsafe.getBooleanVolatile]
> [Registering JNI native method sun.misc.Unsafe.putBooleanVolatile]
> [Registering JNI native method sun.misc.Unsafe.getByte]
> [Registering JNI native method sun.misc.Unsafe.putByte]
> [Registering JNI native method sun.misc.Unsafe.getByteVolatile]
> [Registering JNI native method sun.misc.Unsafe.putByteVolatile]
> [Registering JNI native method sun.misc.Unsafe.getShort]
> [Registering JNI native method sun.misc.Unsafe.putShort]
> [Registering JNI native method sun.misc.Unsafe.getShortVolatile]
> [Registering JNI native method sun.misc.Unsafe.putShortVolatile]
> [Registering JNI native method sun.misc.Unsafe.getChar]
> [Registering JNI native method sun.misc.Unsafe.putChar]
> [Registering JNI native method sun.misc.Unsafe.getCharVolatile]
> [Registering JNI native method sun.misc.Unsafe.putCharVolatile]
> [Registering JNI native method sun.misc.Unsafe.getInt]
> [Registering JNI native method sun.misc.Unsafe.putInt]
> [Registering JNI native method sun.misc.Unsafe.getIntVolatile]
> [Registering JNI native method sun.misc.Unsafe.putIntVolatile]
> [Registering JNI native method sun.misc.Unsafe.getLong]
> [Registering JNI native method sun.misc.Unsafe.putLong]
> [Registering JNI native method sun.misc.Unsafe.getLongVolatile]
> [Registering JNI native method sun.misc.Unsafe.putLongVolatile]
> [Registering JNI native method sun.misc.Unsafe.getFloat]
> [Registering JNI native method sun.misc.Unsafe.putFloat]
> [Registering JNI native method sun.misc.Unsafe.getFloatVolatile]
> [Registering JNI native method sun.misc.Unsafe.putFloatVolatile]
> [Registering JNI native method sun.misc.Unsafe.getDouble]
> [Registering JNI native method sun.misc.Unsafe.putDouble]
> [Registering JNI native method sun.misc.Unsafe.getDoubleVolatile]
> [Registering JNI native method sun.misc.Unsafe.putDoubleVolatile]
> [Registering JNI native method sun.misc.Unsafe.getByte]
> [Registering JNI native method sun.misc.Unsafe.putByte]
> [Registering JNI native method sun.misc.Unsafe.getShort]
> [Registering JNI native method sun.misc.Unsafe.putShort]
> [Registering JNI native method sun.misc.Unsafe.getChar]
> [Registering JNI native method sun.misc.Unsafe.putChar]
> [Registering JNI native method sun.misc.Unsafe.getInt]
> [Registering JNI native method sun.misc.Unsafe.putInt]
> [Registering JNI native method sun.misc.Unsafe.getLong]
> [Registering JNI native method sun.misc.Unsafe.putLong]
> [Registering JNI native method sun.misc.Unsafe.getFloat]
> [Registering JNI native method sun.misc.Unsafe.putFloat]
> [Registering JNI native method sun.misc.Unsafe.getDouble]
> [Registering JNI native method sun.misc.Unsafe.putDouble]
> [Registering JNI native method sun.misc.Unsafe.getAddress]
> [Registering JNI native method sun.misc.Unsafe.putAddress]
> [Registering JNI native method sun.misc.Unsafe.allocateMemory]
> [Registering JNI native method sun.misc.Unsafe.reallocateMemory]
> [Registering JNI native method sun.misc.Unsafe.freeMemory]
> [Registering JNI native method sun.misc.Unsafe.objectFieldOffset]
> [Registering JNI native method sun.misc.Unsafe.staticFieldOffset]
> [Registering JNI native method sun.misc.Unsafe.staticFieldBase]
> [Registering JNI native method sun.misc.Unsafe.ensureClassInitialized]
> [Registering JNI native method sun.misc.Unsafe.arrayBaseOffset]
> [Registering JNI native method sun.misc.Unsafe.arrayIndexScale]
> [Registering JNI native method sun.misc.Unsafe.addressSize]
> [Registering JNI native method sun.misc.Unsafe.pageSize]
> [Registering JNI native method sun.misc.Unsafe.defineClass]
> [Registering JNI native method sun.misc.Unsafe.defineClass]
> [Registering JNI native method sun.misc.Unsafe.allocateInstance]
> [Registering JNI native method sun.misc.Unsafe.monitorEnter]
> [Registering JNI native method sun.misc.Unsafe.monitorExit]
> [Registering JNI native method sun.misc.Unsafe.tryMonitorEnter]
> [Registering JNI native method sun.misc.Unsafe.throwException]
> [Registering JNI native method sun.misc.Unsafe.compareAndSwapObject]
> [Registering JNI native method sun.misc.Unsafe.compareAndSwapInt]
> [Registering JNI native method sun.misc.Unsafe.compareAndSwapLong]
> [Registering JNI native method sun.misc.Unsafe.putOrderedObject]
> [Registering JNI native method sun.misc.Unsafe.putOrderedInt]
> [Registering JNI native method sun.misc.Unsafe.putOrderedLong]
> [Registering JNI native method sun.misc.Unsafe.park]
> [Registering JNI native method sun.misc.Unsafe.unpark]
> [Dynamic-linking native method java.lang.Float.floatToRawIntBits ...  
> JNI]
> [Dynamic-linking native method  
> java.lang.Double.doubleToRawLongBits ... JNI]
> [Dynamic-linking native method  
> sun.reflect.Reflection.getCallerClass ... JNI]
> [Dynamic-linking native method java.lang.String.intern ... JNI]
> [Dynamic-linking native method java.lang.Object.getClass ... JNI]
> [Dynamic-linking native method java.lang.Class.forName0 ... JNI]
> [Dynamic-linking native method
> sun.reflect.Reflection.getClassAccessFlags ... JNI]
> [Dynamic-linking native method
> sun.reflect.NativeConstructorAccessorImpl.newInstance0 ... JNI]
> [Dynamic-linking native method sun.misc.VM.initialize ... JNI]
> [Dynamic-linking native method java.io.FileSystem.getFileSystem ...  
> JNI]
> [Dynamic-linking native method java.io.UnixFileSystem.initIDs ... JNI]
> [Dynamic-linking native method java.lang.System.mapLibraryName ...  
> JNI]
> [Dynamic-linking native method
> java.io.UnixFileSystem.getBooleanAttributes0 ... JNI]
> [Dynamic-linking native method  
> java.io.UnixFileSystem.canonicalize0 ... JNI]
> [Dynamic-linking native method java.lang.ClassLoader 
> $NativeLibrary.load ... JNI]
> [Dynamic-linking native method java.io.FileInputStream.initIDs ...  
> JNI]
> [Dynamic-linking native method java.io.FileDescriptor.initIDs ... JNI]
> [Dynamic-linking native method java.io.FileOutputStream.initIDs ...  
> JNI]
> [Dynamic-linking native method java.lang.System.setIn0 ... JNI]
> [Dynamic-linking native method java.lang.System.setOut0 ... JNI]
> [Dynamic-linking native method java.lang.System.setErr0 ... JNI]
> [Dynamic-linking native method sun.misc.Signal.findSignal ... JNI]
> [Dynamic-linking native method sun.misc.Signal.handle0 ... JNI]
> [Dynamic-linking native method java.lang.Runtime.maxMemory ... JNI]
> [Dynamic-linking native method  
> java.lang.Compiler.registerNatives ... JNI]
> [Registering JNI native method java.lang.Compiler.compileClass]
> [Registering JNI native method java.lang.Compiler.compileClasses]
> [Registering JNI native method java.lang.Compiler.command]
> [Registering JNI native method java.lang.Compiler.enable]
> [Registering JNI native method java.lang.Compiler.disable]
> [Dynamic-linking native method java.lang.ClassLoader.getCaller ...  
> JNI]
> [Dynamic-linking native method java.lang.ClassLoader 
> $NativeLibrary.find ... JNI]
> [Dynamic-linking native method
> java.security.AccessController.doPrivileged ... JNI]
> [Dynamic-linking native method java.io.FileInputStream.open ... JNI]
> [Dynamic-linking native method java.io.FileInputStream.readBytes ...  
> JNI]
> [Dynamic-linking native method java.io.FileInputStream.available ...  
> JNI]
> [Dynamic-linking native method java.lang.reflect.Array.newArray ...  
> JNI]
> [Dynamic-linking native method java.io.FileInputStream.close0 ... JNI]
> [Dynamic-linking native method java.io.UnixFileSystem.list ... JNI]
> [Dynamic-linking native method  
> java.lang.ClassLoader.findLoadedClass0 ... JNI]
> [Dynamic-linking native method  
> java.lang.ClassLoader.findBootstrapClass ... JNI]
> [Dynamic-linking native method
> java.security.AccessController.doPrivileged ... JNI]
> [Dynamic-linking native method java.io.UnixFileSystem.getLength ...  
> JNI]
> [Dynamic-linking native method sun.misc.Perf.registerNatives ... JNI]
> [Registering JNI native method sun.misc.Perf.attach]
> [Registering JNI native method sun.misc.Perf.detach]
> [Registering JNI native method sun.misc.Perf.createLong]
> [Registering JNI native method sun.misc.Perf.createByteArray]
> [Registering JNI native method sun.misc.Perf.highResCounter]
> [Registering JNI native method sun.misc.Perf.highResFrequency]
> [Dynamic-linking native method  
> java.lang.ClassLoader.defineClass1 ... JNI]
> [Dynamic-linking native method  
> java.lang.ClassLoader.resolveClass0 ... JNI]
> [Registering JNI native method Test.testNative]
> [Dynamic-linking native method  
> java.io.FileOutputStream.writeBytes ... JNI]
> My class loader is sun.misc.Launcher$AppClassLoader at b92d342
> Exception in thread "main" java.lang.UnsatisfiedLinkError:  
> Test.testNative()V
> [Dynamic-linking native method  
> java.lang.Throwable.getStackTraceDepth ... JNI]
> [Dynamic-linking native method  
> java.lang.Throwable.getStackTraceElement ... JNI]
> 	at Test.testNative(Native Method)
> 	at Test.<init>(Test.java:4)
>
> Martin
>
> On Wed, Jun 9, 2010 at 03:25, David Holmes <David.Holmes at oracle.com>  
> wrote:
>> Hi Martin,
>>
>> Turns out this is a known (and old) issue (thanks Yuri!):
>>
>> CR 6493522 "JNI_RegisterNatives fails to bind a method of an  
>> uninitialized
>> class"
>>
>> I'll add this email info to the CR.
>>
>> David
>>
>> Martin Buchholz said the following on 06/09/10 09:12:
>>>
>>> Hi ClassLoader maintainers,
>>>
>>> This is a bug report.
>>>
>>> (I think this is a hotspot bug, but it might be a core library
>>> ClassLoader bug or even a URLClassLoader bug)
>>>
>>> If you use RegisterNatives with a class loaded using URLClassLoader,
>>> you must call GetMethodID
>>> before RegisterNatives, or you get an UnsatisfiedLinkError as in the
>>> test case below
>>>
>>> (you will need to edit the below to fill in the location of your jni
>>> include directory and your libjvm.so)
>>>
>>> $ cat Test.java; echo ---------------------; cat jvm.cc; echo
>>> --------------------------; g++ -I$JDK/include -I$JDK/include/linux
>>> -ldl 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 <cstdio>
>>> #include <dlfcn.h>
>>> #include <jni.h>
>>>
>>> JavaVM* jvm;
>>> JNIEnv* env;
>>> const char* libjvm =
>>>    "$JDKDIR/libjvm.so";
>>> const char* loader_url = "file://./";
>>> const char* class_name = "Test";
>>>
>>> void InitializeJVM() {
>>>  JavaVMOption options[1];
>>>  options[0].optionString = (char*)"-Djava.class.path=.";
>>>  //options[1].optionString = (char*)"-verbose:jni";
>>>
>>>  JavaVMInitArgs vm_args;
>>>  vm_args.version = JNI_VERSION_1_2;
>>>  vm_args.options = options;
>>>  vm_args.nOptions = 2;
>>>  vm_args.ignoreUnrecognized = JNI_TRUE;
>>>
>>>  void* handle = dlopen(libjvm, RTLD_LAZY);
>>>  if (handle == NULL) perror("dlopen");
>>>  jint JNICALL (*func_create_java_vm)(JavaVM**, void**, void*) =
>>>      reinterpret_cast<jint JNICALL (*)(JavaVM**, void**, void*)>
>>>      (dlsym(handle, "JNI_CreateJavaVM"));
>>>  if (func_create_java_vm == NULL) perror("dlsym");
>>>  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, "<init>",
>>> "(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, "<init>", "([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);
>>>
>>>  method = env->GetMethodID(cls, "<init>", "()V");
>>>  if (env->ExceptionCheck()) env->ExceptionDescribe();
>>>
>>>  // RegisterNatives must be called after GetMethodID.
>>>  // If the order is reversed, we get UnsatisfiedLinkError,
>>>  // which seems like a bug.
>>>  RegisterNativeMethod(cls);
>>>
>>>  env->NewObject(cls, method);
>>>  if (env->ExceptionCheck()) env->ExceptionDescribe();
>>> }
>>>
>>> int main(int argc, char** argv) {
>>>  InitializeJVM();
>>>  Test();
>>>
>>>  return 0;
>>> }
>>> --------------------------
>>> My class loader is sun.misc.Launcher$AppClassLoader at 1f7182c1
>>> Successfully called registered native method
>>> back to Java
>>>
>>> Thanks,
>>>
>>> Martin
>>




More information about the core-libs-dev mailing list