我遇到了JNI和delphi的问题。
每当我使用以下代码在delphi中创建JVM时:
FillChar(Options, SizeOf(Options), #0);
Options[0].optionString := '-Djava.class.path=' + 'blabla.jar';
VM_args.version := JNI_VERSION_1_2;
VM_args.options := @Options;
VM_args.nOptions := 1;
JVM := TJavaVM.Create(JNI_VERSION_1_6, getJvmPath());
Errorcode := JVM.LoadVM(VM_args);
我尝试使用此代码关闭JVM,但只关闭了一个线程:
JNIEnv.Free;
JNIEnv := nil;
JVM.JavaVM^.DetachCurrentThread(JVM.JavaVM);
JVM.JavaVM^.DestroyJavaVM(JVM.JavaVM);
UnloadJVM;
JVM.Free;
JVM := nil;
我的应用程序创建4-6个线程,线程在这里的最后一行代码中创建。
我尝试使用DetachCurrentThread()
,DestroyJavaVM()
和UnloadJVM
来解决此问题,但最多只有1个线程消失了。
有没有办法摆脱这些线程?
提前致谢!
答案 0 :(得分:2)
根据Java JNI文档,Chapter 5 - The Invocation API:
卸载VM
JNI_DestroyJavaVM()函数卸载Java VM。
从JDK / JRE 1.1开始,只有主线程可以通过调用DestroyJavaVM来卸载VM。从JDK / JRE 1.2开始,限制被删除,任何线程都可以调用DestroyJavaVM来卸载VM。
VM在实际卸载之前等待当前线程是唯一的非守护程序用户线程。
用户线程包括Java线程和附加的本机线程。
存在此限制是因为Java线程或附加的本机线程可能正在保留系统资源,例如锁,窗口等。 VM无法自动释放这些资源。
通过将当前线程限制为卸载VM时唯一正在运行的线程,释放任意线程持有的系统资源的负担在程序员身上。
VM不会自动完成你的线程,并且在它们终止之前它不会完全卸载。
你自己的线程完成了你的责任,但我猜你所引用的额外线程是在加载时由JVM本身创建的。
另请注意,JNI文档有些含糊不清:
DestroyJavaVM
卸载Java VM并回收其资源。
在JDK / JRE 1.1中,对DestroyJavaVM的支持尚未完成。从JDK / JRE 1.1开始,只有主线程可以调用DestroyJavaVM。
从JDK / JRE 1.2开始,任何线程(无论是否附加)都可以调用此函数。如果附加了当前线程,则VM将等待,直到当前线程是唯一的非守护程序用户级Java线程。如果未附加当前线程,则VM会附加当前线程,然后等待,直到当前线程是唯一的非守护程序用户级线程。
然而,JDK / JRE仍然不支持VM卸载。
因此,似乎无论如何在程序退出之前JVM都没有完全卸载。