我的DLL代码来自exe文件,但无法从Java loadLibrary加载

Log*_*gan 16 java dll java-native-interface loadlibrary

我创建了一个C++模块来构建一个共享库文件,然后使用JNI从Java调用它.

我有两个环境,Windows和Unix,我有一个C++可执行程序和一个Java程序,我只是为每个环境重新编译.

  • 当我在Unix中编译我的tester.exe程序并使用我的库(.so)中的方法运行它时,它工作正常.
  • 当我在Unix中编译我的Java程序并使用Java的loadLibrary加载我的库(.so)时,它工作正常.
  • 当我在Windows中编译tester.exe程序并使用我的库(.dll)中的方法运行它时,它工作正常.就像unix版本一样.

  • 当我在Windows中编译我的Java程序并使用Java的loadLibrary加载我的库(.dll)时,它失败了.它说尝试访问无效地址.

我无法弄清楚为什么它在Windows中运行时无法使用Java loadLibrary,但它可以在其他地方使用相同的代码.如果我延迟加载我的库使用的依赖DLL,那么我的库在Java中加载但不起作用.我知道有一些特定的代码导致Java加载我的库的问题,但我无法弄清楚为什么我的C++ exe对相同的方法和库没有问题.


我的dll有一个公开的方法,它从一些现有的库中调用4个方法.如果我评论这4个方法,那么我的DLL加载Java很好.我知道这与我的dll链接到的库中的这些方法有关.Java是如何看待依赖库的?我首先尝试加载依赖库,但是我加载的一个dll文件导致递归错误并且堆栈溢出.

任何人都知道一种方法导致堆栈从递归错误溢出?我需要其中的方法,但我不能用java loadLibrary加载它.


以下是有关所涉及文件和实际错误消息的更多详细信息.我在我的inital dll文件中添加了一个DllMain,只是为了看看什么载荷和什么时候.如果我将同一个程序(my_plain_dll_to_call_JNI_DLL)编译为exe文件,一切正常.如果我编译它并从我的java程序加载它会发生这种情况.

  • myJavaProgram,只需调用System.loadLibrary()来加载一个基本的.dll文件,该文件调用我的另一个包含JNI代码的dll中的方法.
  • my_plain_dll_to_call_JNI_DLL是我创建的一个dll,它是通过将它链接到我的dll库文件来测试依赖项.它只是从另一个调用我需要的本机代码的dll调用一个方法.
  • my_JNI_DLL.ll是一个与我需要从JNI访问的现有C++编程库链接的DLL文件.它包含对现有源代码库中方法的直接调用.

我写了文件名,显示每行左边的文本,以显示执行所在的层.


c:\java myJavaProgram
myJavaProgram: Java Static Method Entry.

myJavaProgram: Java Calling System.loadLibrary(my_plain_dll_to_call_JNI_DLL)

my_JNI_DLL.dll: Entering DllMain

my_JNI_DLL.dll: DLL_PROCESS_ATTACH

my_plain_dll_to_call_JNI_DLL: DLL_PROCESS_ATTACH
my_plain_dll_to_call_JNI_DLL: DLL_THREAD_ATTACH
my_plain_dll_to_call_JNI_DLL: DLL_THREAD_DETACH
my_plain_dll_to_call_JNI_DLL: DLL_PROCESS_DETACH

myJavaProgram: my_plain_dll_to_call_JNI_DLL Loaded!

myJavaProgram: Java Static Method Exit.

myJavaProgram: Entering Main().

my_plain_dll_to_call_JNI_DLL: In call_my_JNI_DLL_method

my_JNI_DLL.dll: In my_JNI_DLL_method

my_JNI_DLL.dll: Entering my_JNI_DLL_CheckEnvironmentVariables()

my_JNI_DLL.dll: Exiting my_JNI_DLL_CheckEnvironmentVariables

my_JNI_DLL.dll: Calling StartExistingNativeCode.

#
# A fatal error has been detected by the Java Runtime Environment:
#
#  Internal Error (0xc0fb007e), pid=7500, tid=7552
#
# JRE version: 6.0_21-b06
# Java VM: Java HotSpot(TM) Client VM (17.0-b16 mixed mode, sharing windows-x86 )
# Problematic frame:
# C  [KERNELBASE.dll+0x9673]
#
# An error report file with more information is saved as:
# C:\hs_err_pid7500.log
#
# If you would like to submit a bug report, please visit:
#   http://java.sun.com/webapps/bugreport/crash.jsp
# The crash happened outside the Java Virtual Machine in native code.
# See problematic frame for where to report the bug.
#

my_plain_dll_to_call_JNI_DLL: DLL_PROCESS_DETACH

my_JNI_DLL.dll: Entering DllMain

my_JNI_DLL.dll DLL_PROCESS_DETACH


更新 我已将问题缩小到内存管理库,该库与我的程序使用的另一个DLL链接.它使用的DLL是sh33w32.dll,它被称为SmartHeap,我认为是一家名为Microquil的公司.我有3.3版,当Java LoadLibrary尝试加载该DLL时,它失败了.我不知道如何让java处理加载该库.它必须与Java可以访问的内存区域相关,而不是允许exe访问的窗口.exe对SmartHeap库没有问题,但Java不允许我使用它.处理这个的任何想法或经验?我试图通过重新编译其他库来删除链接库,但是代码中的正常调用失败,通常工作.


发现附加信息无法在java中加载的DLL中的函数称为MemRegisterTask.它来自Microquill的SmartHeap产品.这是我发现的关于此功能的文档.我认为这种内存分配是导致java无法加载它的原因.

MemRegisterTask初始化SmartHeap库.在大多数平台上,您不需要调用MemRegisterTask,因为SmartHeap将在您进行第一次调用时自行初始化.

SmartHeap维护每个任务或流程的注册引用计数.每次调用MemRegisterTask时,此引用计数都会递增.如果您的应用程序准备好终止之前最后一次调用SmartHeap,则可以调用MemUnregisterTask来终止SmartHeap.MemUnregisterTask将注册引用计数减1 - 当计数为零时,SmartHeap将释放任何SmartHeap分配的内存和与当前任务或进程关联的调试状态.

Dmi*_*kov 0

对我来说,看起来像是调用约定或类型大小不匹配。每个 Windows C 编译器都有其自己的一组特性,并且 Windows JNI 标头假定 Microsoft Visual C++(最新版本)。仔细查看警告 - 精度下降是不好的迹象。

例如,__int64是 MSVC 特定的。您需要找出 Borland C 中 64 位整数类型的名称并将其映射到__int64包含jni.h.