Reputation: 11
I have a problem with the JNI and delphi.
Whenever I create a JVM in delphi with this code:
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);
I try to close the JVM with this code, but only 1 thread get closed:
JNIEnv.Free;
JNIEnv := nil;
JVM.JavaVM^.DetachCurrentThread(JVM.JavaVM);
JVM.JavaVM^.DestroyJavaVM(JVM.JavaVM);
UnloadJVM;
JVM.Free;
JVM := nil;
My application creates 4-6 threads, the threads are created at the last line of code here.
I tried to use DetachCurrentThread()
, DestroyJavaVM()
and UnloadJVM
to resolve this issue, but then only 1 thread disappears max.
Is there a way to get rid of those threads?
Thanks in advance!
Upvotes: 1
Views: 747
Reputation: 3401
According to Java JNI documentation, Chapter 5 - The Invocation API:
Unloading the VM
The JNI_DestroyJavaVM() function unloads a Java VM.
As of JDK/JRE 1.1, only the main thread could unload the VM, by calling DestroyJavaVM. As of JDK/JRE 1.2, the restriction was removed, and any thread may call DestroyJavaVM to unload the VM.
The VM waits until the current thread is the only non-daemon user thread before it actually unloads.
User threads include both Java threads and attached native threads.
This restriction exists because a Java thread or attached native thread may be holding system resources, such as locks, windows, and so on. The VM cannot automatically free these resources.
By restricting the current thread to be the only running thread when the VM is unloaded, the burden of releasing system resources held by arbitrary threads is on the programmer.
The VM will not automatically finalize your threads, and it will not completely unload until they terminate.
It is your responsability that your own threads get finished, but I guess that the extra threads that you are referring are created by the JVM itself when loaded.
Also note that the JNI documentation is somewhat ambiguous:
DestroyJavaVM
Unloads a Java VM and reclaims its resources.
The support for DestroyJavaVM was not complete in JDK/JRE 1.1. As of JDK/JRE 1.1 Only the main thread may call DestroyJavaVM.
Since JDK/JRE 1.2, any thread, whether attached or not, can call this function. If the current thread is attached, the VM waits until the current thread is the only non-daemon user-level Java thread. If the current thread is not attached, the VM attaches the current thread and then waits until the current thread is the only non-daemon user-level thread.
The JDK/JRE still does not support VM unloading, however.
So it seems that anyway the JVM is not completely unloaded until the program exits.
Upvotes: 2