Must call RegisterNatives after getMethodID, else get UnsatisfiedLinkError

David Holmes David.Holmes at oracle.com
Wed Jun 9 22:48:06 UTC 2010


Kelly O'Hair said the following on 06/10/10 05:52:
> 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.

Yes but in this case they are actually creating their own classloader 
from native code and using that to load the target class. Of course in 
theory they could still load it in a such a way that the class is also 
initialized, but it might not be appropriate for class initialization to 
occur at this time - hence the approach taken.

Cheers,
David

> 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