我有一个Windows MFC应用程序,该应用程序:

(1)加载JVM(JNI_CreateJavaVM())

(2)将主线程附加到JVM(AttachCurrentThread())

(3)加载一些Java类和方法(FindClass()GetMethodID()/GetStaticMethodID())

(4)注册一些 native 回调以供Java代码(RegisterNatives())使用

(5)从JVM(DetachCurrentThread())分离线程

(6)销毁JVM(DestroyJavaVM())

我运行该应用程序时,以上所有功能都会成功。我知道它们成功了,因为除了上述内容之外,我还与应用程序进行了交互并成功调用了Java静态方法,而这些Java方法成功地调用了我的 native 回调。我的应用程序正常退出,并且可以确定已经执行了预期的Java函数和 native 回调。

但是,每隔我运行该应用程序一次,对JNI_CreateJavaVM()的调用就会失败(不会填充JavaVM *)。 在应用程序的运行之间绝对没有任何变化。我只运行了一次(成功,即使没有执行上述6个步骤,也没有做任何事情),优雅地退出,再次运行,然后来回失败。来回的成功/失败没有异常(exception)-我可以运行数十次,并且在成功与失败之间的每隔一次精确的振荡就发生在JNI_CreateJavaVM()行上。

如有必要,我将粘贴更多代码。但是,我希望有人能对我提供的内容有所了解。 (注意:这是BCGSoft MFC属性表应用程序,尽管我对此表示强烈怀疑。)

最佳答案

好像您遇到了this bug(重述的here),可能永远都不会修复。

尽管它的名字,DestroyJavaVM()实际上并没有破坏JVM。它所做的是向JVM发出信号,表明它应该关闭,但是JVM实际上一直等到除Main线程之外的所有其他线程都已停止,然后才真正关闭。实际上,即使这样,它仍然无法完全清除,就像the documentation指出(相当多cryptically):“但是,JDK/JRE仍然不支持VM卸载。”

另外,我担心您的第2步“将主线程附加到JVM”。您不需要将创建JVM的线程附加到JVM,也可以不分离该线程。如果您确实这样做,那么很可能是造成系统困惑的原因。 (创建JVM的线程是JVM的“主”线程。仅在需要访问JVM的情况下,才需要将其他 native 线程附加/分离。)

顺便说一句,JNI_CreateJavaVM()成功返回0,您说它在“失败”次数返回0,那么从什么意义上讲它失败了?您正在使用哪个JVM(版本,供应商)?

09-06 17:07
查看更多