通过Delphi中的JNI创建的JVM创建了多个线程

时间:2014-07-15 10:33:32

标签: multithreading delphi jvm java-native-interface delphi-xe2

我遇到了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个线程消失了。

有没有办法摆脱这些线程?

提前致谢!

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都没有完全卸载。