我有一个Windows MFC应用程序:
(1)加载JVM(JNI_CreateJavaVM()
)
(2)将主线程附加到JVM(AttachCurrentThread()
)
(3)加载一些Java类和方法(FindClass()
和GetMethodID()
/ GetStaticMethodID()
)
(4)注册一些本机回调以供Java代码(RegisterNatives()
)
(5)从JVM(DetachCurrentThread()
)
(6)销毁JVM(DestroyJavaVM()
)
以上所有功能每隔一段时间成功我运行应用程序。我知道他们成功了,因为除了上面的内容,我还与应用程序交互并成功调用Java静态方法,这些Java方法成功调用了我的本机回调。我的应用程序优雅地退出,并且可以确定已经执行了预期的Java函数和本机回调。
但是,每隔一次我运行应用程序,对JNI_CreateJavaVM()
的调用失败(不填充JavaVM *
)。 应用程序运行之间绝对没有任何变化。我只是运行一次(成功,甚至没有做除了上述6个步骤之外的任何事情),优雅地退出,再次运行,它来回失败。前后成功/失败没有例外 - 我可以运行数十次,并且它在成功之间每隔一段时间就会振荡,并且在JNI_CreateJavaVM()
线上失败。
如有必要,我会粘贴更多代码。但是,我希望有人能够了解我所提供的内容。 (注意:这是一个BCGSoft MFC属性表应用程序,但我强烈怀疑这很重要。)
答案 0 :(得分:4)
看起来你遇到了this bug(重述here),这可能永远不会被解决。
尽管它的名字,DestroyJavaVM()
实际上并没有破坏JVM。它的作用是向JVM发出它应该关闭的信号,但是JVM实际上等待直到主线程以外的所有线程在实际关闭之前停止。实际上,即使这样,它也不会完全清理,因为the documentation表示(非常cryptically):“但JDK / JRE仍然不支持VM卸载。”
另外,我关注你的第2步,“将主线程附加到JVM”。您不需要将创建JVM的线程附加到JVM,也可以不分离该线程。如果你真的这样做,那么可能就是弄乱你的系统。 (创建JVM的线程是JVM的“主”线程。如果需要访问它,您只需要将其他本机线程附加/分离到JVM。)
顺便说一句,JNI_CreateJavaVM()
成功时返回0,你说它在“失败”时间返回0,那么它在什么意义上失败了?您使用的是哪个JVM(版本,供应商)?