JNI_CreateJavaVM() 运行正常1x,但之后:失败,结果:-5Win64,Cython,Python

问题描述

错误

不会在运行 1 时发生,但在任何后续运行中,Python 内核都会死掉并且必须重新启动:

JNI_CreateJavaVM() Failed with result: -5
[SpyderKernelApp] WARNING | No such comm: aa125bd78d0711ebb9a2001a7dda7113 

环境

  • 截至 2021 年 3 月的所有当前
  • Win64
  • Anaconda(实际上是迷你蟒蛇)
  • Win64 的 Java 运行时
  • Saxon/C(为 Win64 编译)1.2.1 与 Saxonica 的 Saxon-HE 9.9.1.5C 一起运行

测试脚本

这些 Saxon/c 提供的测试脚本产生相同的行为。运行OK一次但在第二次运行时导致 python 内核崩溃:

  • saxon_example.py
  • saxon_example2.py
  • saxon_example3.py

猜测?

在交叉编译、cython、C++、JNI 等方面没有深入的经验。

也许第一个这样的 JNI 请求在 Windows 上加载 JavaVM 并且它保持运行。 (...它最终如何知道退出?)通过 JNI 的后续请求不会发送到正确的内存位置,即 “警告 | 没有这样的通信:aa125bd78d0711ebb9a2001a7dda7113”?指针问题?

尝试 1 删除了所有先前版本的 Java 运行时 (win64)。重新安装最新的 Java 运行时。没有变化。

更新 2

安德鲁,感谢您提供信息。

我发现这种情况有几个“层次”。我试图从 Python 运行的库是 saxon/c。 Saxon 最初是 Java,使用 Excelsior JET Enterprise 15.3 MP1 (10/2019) 编译为目标代码(与 Win64 兼容)。其他部分在 C 和 C++ 中使用 Windows Visual C++ 编译器编译。最后在构建过程中也使用了 cpython。

很确定传统的 Java 运行时(不需要运行典型的 JAR 文件,因为 Excelsior 会产生目标代码?我认为 Excelsior JET Enterprise 确实为其 Java 编译器提供了一些辅助目标代码,与 Visual C++ 要求的非常相似运行时间。所以我不确定 JNI 代码是如何合并的?

给情况增添了一些“迷雾”——总部位于俄罗斯的 Excelsior 退出,Java 编译器业务,取消了所有支持,据报道卖给了中国电信公司华为,华为迅速删除了 Excelsior 网站的所有痕迹。 (编不下去了!)

python 脚本运行一次正常,但在第二次运行时,它们使 python 内核崩溃,并出现 JNI 通信错误。以某种方式重新启动 python 内核修复了问题,但所有试图摆脱 saxonc.PySaxonProcessor 对象的尝试都无效。

import saxonc

with saxonc.PySaxonProcessor(license=False) as proc:
   print(dir(proc))  #shows proc is running

proc.release()
proc=None
del proc
'''

解决方法

Java's Chapter 5: The Invocation API DestroyJavaVM() documentation(我的粗体):

销毁JavaVM

jint DestroyJavaVM(JavaVM *vm);

卸载 Java VM 并回收其资源。

任何线程,无论是否附加,都可以调用此函数。如果 当前线程已附加,VM 等待直到当前线程 唯一的非守护程序用户级 Java 线程。如果当前线程是 未附加,VM 附加当前线程,然后等待直到 当前线程是唯一的非守护程序用户级线程。

链接:

JavaVM 接口函数表中的索引 3。

参数

vm:将被销毁的 Java VM。

退货:

成功返回JNI_OK;返回一个合适的 JNI 错误代码(a 负数)失败。

不支持卸载 VM。

注意最后一个:

不支持卸载虚拟机。

您只能在一个进程中创建一个 JVM 实例。曾经。