我对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来解决这个问题,但是最多只有一个线程消失。
有没有办法摆脱这些线程?
提前感谢!
发布于 2014-07-16 01:52:32
根据Java JNI文档,Chapter 5 - The Invocation API
卸载虚拟机
函数的作用是:卸载一个Java。
在JDK/JRE1.1中,只有主线程可以通过调用DestroyJavaVM来卸载VM。从JDK/JRE1.2开始,这个限制被删除了,并且任何线程都可以调用DestroyJavaVM来卸载VM。
在VM实际卸载之前,它会一直等到当前线程成为唯一的非守护进程用户线程。
用户线程包括Java线程和附加的本机线程。
之所以存在此限制,是因为Java线程或附加的本机线程可能持有系统资源,如锁、窗口等。VM不能自动释放这些资源。
通过在卸载VM时将当前线程限制为唯一运行的线程,释放由任意线程持有的系统资源的负担由程序员承担。
VM不会自动完成您的线程,并且在线程终止之前它不会完全卸载。
完成您自己的线程是您的责任,但我猜您引用的额外线程是由JVM本身在加载时创建的。
还要注意,JNI文档有些模棱两可:
DestroyJavaVM
卸载Java VM并回收其资源。
在JDK/JRE1.1中,对DestroyJavaVM的支持并不完整。在JDK/JRE1.1中,只有主线程可以调用DestroyJavaVM。
从JDK/JRE 1.2开始,任何线程,无论是否连接,都可以调用此函数。如果附加了当前线程,则VM将一直等待,直到当前线程成为唯一的非守护程序用户级Java线程。如果当前线程未附加,则VM附加当前线程,然后等待,直到当前线程成为唯一的非守护程序用户级线程。
但是,JDK/仍然不支持VM卸载。
所以看起来在程序退出之前JVM并没有完全卸载。
https://stackoverflow.com/questions/24755926
复制相似问题