java - 调用 JNI_CreateJavaVM 使程序崩溃

标签 java assembly jvm java-native-interface jrockit

我有一个 C DLL,它使用 JNI 来代理对执行实际举重的底层 Java 程序的任何调用。我正在动态加载 jrockit jvm.dll 以进行函数调用。

供应商 A 有一个 C# DLL,它实际上调用了我的 C DLL,另一个供应商 B 有一个 C# 程序,它调用了供应商 A 的 C# DLL。

使用供应商 A 的 C# DLL 进行测试时没有任何问题,但在与供应商 B 的 C# 程序集成后,我通过 JNI_CreateJavaVM 调用初始化 JVM 导致整个程序崩溃。

如有任何帮助,我们将不胜感激。

我收到的错误消息是:

[ERROR] Could not find allocated thread local data key in TIB
[ERROR] Could not create fast TLD
JRockit aborted: Unspecified Error(52)
Assertion failed: Could not create fast tld 
In vmDebug Before Abort() (src/jvm/runtime/debug/debug.c:103)

编辑 1: 好的,我已经反汇编了 jvm.dll,它正在调用 TlsAlloc,然后调用 TLSSet 并到达显示错误消息的代码,第二张图片中 je SHORT 04755D4B 之前的 cmp esi、edx 不能相等。

第一张图中call 04755DD0的内容在第二张图中。

有谁知道之前的计算(操作esi和edx的1)是做什么的?

Disassembly 1 Disassembly 2

编辑 2:(回应 P.T.) 我没有设置任何特定的线程系统,所以我认为它使用的是默认的线程系统,根据此处的说明,它是 native 的:http://docs.oracle.com/cd/E13222_01/wls/docs81b/jrockit/threads.html

你的猜测很可能是正确的,在查看反汇编时,我发现代码逻辑是这样的,它首先调用 TlsAlloc,然后调用 TlsSetValue 将 TlsAlloc 返回的索引处的线程本地存储设置为4711 的常量魔数(Magic Number),之后它使用 eip 从线程信息 block 的开始循环寻找值 4711,一旦找到它,代码然后再次调用 TlsSetValue 将值设置为 1147,此时它检查 eip 是否是通过确保 [eip] 设置为 1147,实际指向线程本地存储。

供应商 B 在他们的程序中使用 C#,因此,他们将使用 CLR 虚拟机。一旦达到供应商 B 调用我的 DLL 的程度,他们就已经初始化了 WPF 棱镜和 mef 框架,将所有接口(interface)模块加载到各自的位置,初始化了所有单例(WPF 棱镜术语中的导出)模型并初始化了 MS 工作流。但是,当我将初始化代码移到前几行时,jvm 成功初始化(这不是初始化 jvm 的正确位置,我们还没有测试其余代码是否有效)。

代码只在TlsSetValue失败时跳转到错误,请问TlsSetValue失败有什么原因吗?在可能导致问题的供应商 B 的代码中我应该注意什么?

最佳答案

我遇到了同样的错误,我设法弄清楚发生了什么,至少在我的情况下是这样。它看起来像是 JRockit 中的错误,您的问题对调查它很有帮助。

为放置在插槽中的“魔数(Magic Number)”执行的搜索从 TEB 的开头开始延伸到两页数据。但是,TEB 本身只有 64 个存储槽。参见 http://msdn.microsoft.com/en-gb/library/windows/desktop/ms686708(v=vs.85).aspx .

如果分配的存储槽索引为 64 或更高,Windows 不会将数据放入嵌入式数组中,而是将其放入 TlsExpansionSlots 指针指向的 block 中。由于这是在 TEB 之外,因此对魔数(Magic Number)的搜索失败并且 JRockit 产生此错误。

我的实例也发生在 .NET 程序中。我的猜测是 CLR 大量使用了 TLS,因此更有可能分配高槽号。

在我的例子中,JRockit 在尝试写入日志行时实际上崩溃了,可能是因为它发生得太早以至于日志尚未创建。不确定您使用的是哪个版本的 JRockit。我的是:

C:\>java -version
java version "1.6.0_14"
Java(TM) SE Runtime Environment (build 1.6.0_14-b08)
BEA JRockit(R) (build R27.6.5-32_o-121899-1.6.0_14-20091001-2107-windows-ia32, compiled mode)

不知道以后的版本会不会修复。如果不是,我们(即我的雇主)可能不得不向 Oracle 提出。

关于java - 调用 JNI_CreateJavaVM 使程序崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14150746/

相关文章:

assembly - 如何更改程序集中当前光标位置的背景颜色

api - JDK对自己的api有一些优化吗?

Java servlet - 用于代码安全连接的 TLS 日志版本?

java - 值应该只匹配数字、点和逗号

java - 内部服务器错误

Java 字符串池和类型转换

java - Solr 和 JVM 内存管理问题

java - 使用 while 循环打印用户请求的次数

Linux 汇编 x86 |试图获取堆栈值,语法错误

go - Go汇编中PCDATA是什么意思