-
Notifications
You must be signed in to change notification settings - Fork 173
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
JNI methods cannot be attached inside clinit #277
Comments
Can you provide a complete test case? I just tried to reproduce it with the following patch, but was unable to do so.
|
OK, so it turns out that I am being confused by the stack traces Avian generates. Sorry, I don't have much experience of stepping through a JITC VM in a debugger. The stack trace I get looks like this, after I added an assert that c is != NULL at the top of RegisterNatives. Because this argument comes directly from a call to FindClass I assumed it had returned null. thread #1: tid = 0x1a03, 0x00007fff8c3ac866 libsystem_kernel.dylib Stepping through in the debugger though, I end up quite confused. What I actually see is: env->FindClass -> findClass -> resolveClass -> resolveSystemClass which fails to find the class and then calls vm::throw with an exception. After attempting to step over the vm::throw statement I end up hitting that assert, so I assume at this point Avian unwinds the stack and I don't get to see what caught the exception, presumably something deep inside the JNI machinery. So the issue is quite clearly that it's getting stuck trying to find the class that's in the process of classloading. To see what I see, do this: git clone https://github.com/wg/scrypt.git $AVIAN_HOME/build/darwin-x86_64-debug-openjdk-src/avian -cp $HOME/.m2/repository/junit/junit/4.11/junit-4.11.jar:/$HOME/.m2/repository/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar:target/scrypt-1.4.0.jar:target/test-classes org.junit.runner.JUnitCore com.lambdaworks.crypto.test.SCryptTest |
IIRC, when you throw an exception in either vm-internal code or JNI code, it doesn't immediately unwind the stack - rather, it sets an exception flag on the thread, and waits until we return out of native code before unwinding the java stack. The expectation is that the native code will detect the presence of the exception (either by reading the flag, or from return codes) and return as quickly as possible. In short, I think seeing a throw in native code and then returning null is a normal course of action. |
That doesn't seem to be what happens in lldb, but debuggers are weird :) I can well believe actual control flow is not the same as what appears to happen inside the debugger. At any rate, I'm not sure why your test passes and yet this code goes wrong. It feels like the same issue! :) |
Sorry, I think I just confused the issue. I was referring to how the scrypt code should probably read something like:
That issue aside, my best guess would be that the problem is that in the JNI_OnLoad, we haven't registered any of the application class loaders - and so the only one available is the system one, which only loads from the internal jar. @dicej, does that sound plausible? |
Ah yes. Scrypt lib does indeed load a library from its own jar. I thought it unpacked it first but maybe not. |
On Mon, 23 Jun 2014, Mike Hearn wrote:
Thanks for the test case. The problem is that FindClass uses the class Looking at openjdk/hotspot/src/share/vm/prims/jni.cpp, I see that HotSpot |
Thanks! I can see there's an easy workaround on the scrypt library side. Let me know if I can help in any way. |
Thanks guys, you really do rock. |
Consider FooClass. -> System.loadLibrary() -> libfoo -> clazz = JNI_FindClass("FooClass"); JNI_RegisterNatives(clazz, "nativeMethod", ...);
On Avian the JNI_FindClass call fails and returns null, presumably because it's called inside the class static initialiser so the class didn't init yet. This means that the scrypt library cannot initialise and indeed crashes the VM because it ends up passing a null class ptr to RegisterNatives.
The text was updated successfully, but these errors were encountered: