我有一个 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 不能相等。
第一个图像中调用 04755DD0 的内容在第二个图像中。
有谁知道之前的计算(操作 esi 和 edx 的 1)是做什么的?
编辑 2:(响应 PT)我没有设置任何特定的线程系统,所以我想它使用的是默认的线程系统,根据这里:http ://docs.oracle.com/cd/E13222_01/ wls/docs81b/jrockit/threads.html
你的猜测很可能是正确的,在查看反汇编时,我发现代码逻辑是这样的,它首先调用 TlsAlloc 然后调用 TlsSetValue 将 TlsAlloc 返回的索引处的线程本地存储设置为常量幻数4711 之后它使用 eip 从线程信息块的开头循环查找值 4711,一旦找到它,代码然后再次调用 TlsSetValue 将值设置为 1147,此时它检查 eip 是否实际指向通过确保将 [eip] 设置为 1147 来获取线程本地存储。
供应商 B 在他们的程序中使用 C#,因此,他们将使用 CLR 虚拟机。一旦它到达供应商 B 调用我的 DLL 的点,他们将已经初始化 WPF prism 和 mef 框架,将所有接口模块加载到各自的位置,初始化所有单例(WPF prism 术语中的导出)模型并初始化 MS 工作流。但是,当我将初始化代码移至前几行时,jvm 初始化成功(这不是初始化 jvm 的正确位置,我们尚未测试其余代码是否有效)。
代码仅在 TlsSetValue 失败时分支到错误,是否有任何原因导致 TlsSetValue 失败?我应该在供应商 B 的代码中寻找可能导致问题的哪些内容?