Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JNI_CreateJavaVM() fails every other time I run my application (exactly)

I have a Windows MFC application that:

(1) Loads the JVM (JNI_CreateJavaVM())

(2) Attaches the main thread to the JVM (AttachCurrentThread())

(3) Loads some Java classes and methods (FindClass() and GetMethodID() / GetStaticMethodID())

(4) Registers some native callbacks for use by Java code (RegisterNatives())

(5) Detaches the thread from JVM (DetachCurrentThread())

(6) Destroys the JVM (DestroyJavaVM())

All of the above functions succeed every other time I run the application. I know they succeed, because, additionally to the above, I interact with the application and successfully call Java static methods, and these Java methods successfully call my native callbacks. My application exits gracefully, and it is certain that the expected Java functions, and native callbacks, have been executed.

However, every other time that I run the application, the call to JNI_CreateJavaVM() fails (not populating the JavaVM *). Absolutely nothing changes between runs of the application. I simply run it once (successfully, even without doing anything except the above 6 steps), quit gracefully, run again, and it fails, back and forth. There are no exceptions to the back-and-forth success/failure - I can run it dozens of times, and it oscillates precisely every other time between success, and failing on the JNI_CreateJavaVM() line.

If necessary, I will paste more code. However, I hope somebody has an insight with what I've provided. (Note: this is a BCGSoft MFC property-sheet application, though I strongly doubt that matters.)

like image 725
Dan Nissenbaum Avatar asked May 04 '12 06:05

Dan Nissenbaum


1 Answers

It looks like you are running into this bug (restated here) that is probably never going to be fixed.

Despite its name, DestroyJavaVM() does not actually destroy the JVM. What it does is signal the JVM that it should shut down, but the JVM actually waits until all the threads other than the Main thread have stopped before it actually shuts down. In fact, even then it does not fully clean up after itself, as the documentation states (quite cryptically): "The JDK/JRE still does not support VM unloading, however."

Also, I'm concerned about your step 2, "Attaches the main thread to the JVM". You do not need to attach the thread that created the JVM to the JVM and you may not detach that thread. If you really are doing that, then it's possible that is what is messing up your system. (The thread that creates the JVM is the JVM's "Main" thread. You only need to attach/detach other native threads to the JVM if they need access to it.)

By the way, JNI_CreateJavaVM() returns 0 on success, and you say it returns 0 the "failed" times, so in what sense is it failing? Which JVM (version, vendor) are you using?

like image 99
Old Pro Avatar answered Sep 19 '22 06:09

Old Pro