Мой код dll работает из исполняемого файла, но не загружается из Java loadLibrary

Я создал модуль C++ для встраивания в файл общей библиотеки, а затем вызываю его из Java с помощью JNI.

У меня есть 2 среды, Windows и Unix, и у меня есть исполняемая программа на C++ и программа на Java, которые я просто перекомпилирую для каждой среды.

  • Когда я компилирую свою программу tester.exe в Unix и запускаю ее с помощью методов из моей библиотеки (.so) работает нормально.
  • Когда я компилирую свою Java-программу в Unix и загружаю свою библиотеку (.so) с помощью Java loadLibrary работает нормально.
  • Когда я компилирую свою программу tester.exe в Windows и запускаю ее с помощью методов из моей библиотеки (.dll) работает нормально. Как и юникс версия.

  • Когда я компилирую свою Java-программу в Windows и загружаю свою библиотеку (.dll) с помощью Java loadLibrary, происходит сбой. Пишет Попытка доступа недействительный адрес.

Я не могу понять, почему он не будет работать с Java loadLibrary при работе в Windows, но он работает везде, используя тот же код. Если я откладываю загрузку зависимой DLL, которую использует моя библиотека, моя библиотека загружается на Java, но не работает. Я знаю, что есть определенный код, который вызывает проблему с загрузкой моей библиотеки Java, но я не могу понять, почему мой C++ exe не имеет проблем с теми же методами и библиотеками.


Моя dll имеет 1 открытый метод, который вызывает 4 метода из некоторых существующих библиотек.Если я прокомментирую эти 4 метода, моя dll нормально загрузится в Java. Я знаю, что это как-то связано с этими методами из библиотеки, на которую ссылается моя dll. Есть ли что-то другое в том, как Java видит зависимые библиотеки? Я попытался сначала загрузить зависимые библиотеки, но один из загружаемых файлов dll вызывает ошибку рекурсии, и стек переполняется.

Кто-нибудь знает, как обойти DLL, вызывающую переполнение стека из-за ошибки рекурсии? Мне нужны методы в нем, но я не могу загрузить его с помощью java loadLibrary.


Вот более подробная информация о задействованных файлах и фактических сообщениях об ошибках. Я добавил DllMain в свой исходный файл dll, чтобы посмотреть, что и когда загружается. Если ту же программу (my_plain_dll_to_call_JNI_DLL) скомпилировать как exe-файл, то все работает нормально. Если я скомпилирую его и загружу из своей Java-программы, это произойдет.

  • myJavaProgram просто вызывает System.loadLibrary() для загрузки базовой библиотеки .dll. файл, который вызывает метод в моей другой dll, содержащий код JNI.
  • my_plain_dll_to_call_JNI_DLL — это dll, которую я создал, связав ее с моим dll только для проверки зависимости. Он просто вызывает метод из другой dll, которая вызывает нужный мне собственный код.
  • my_JNI_DLL.ll — это DLL-файл, связанный с существующим программным обеспечением на C++. библиотеки, к которым мне нужно получить доступ из JNI. Он содержит прямые вызовы методы в существующих библиотеках исходного кода.

Я написал имя файла, отображающее текст слева от каждой строки, чтобы показать, на каком уровне выполняется выполнение.


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, а не к тому, к чему Windows разрешает доступ exe. У exe нет проблем с библиотекой SmartHeap, но Java не позволит мне ее использовать. Любые идеи или опыт борьбы с этим? Я попытался удалить связанную библиотеку, перекомпилировав другие библиотеки, но тогда обычные вызовы в коде перестали работать.


Найдена дополнительная информация Функция в dll, которая не загружается в java, называется MemRegisterTask. Это продукт под названием SmartHeap от Microquill. Вот документация, которую я нашел об этой функции. Я думаю, что это распределение памяти является причиной того, что java не может ее загрузить.

MemRegisterTask инициализирует библиотеку SmartHeap. На большинстве платформ вам не нужно вызывать MemRegisterTask, потому что SmartHeap инициализируется при первом вызове.

SmartHeap поддерживает счетчик регистрационных ссылок для каждой задачи или процесса. Каждый раз, когда вы вызываете MemRegisterTask, этот счетчик ссылок увеличивается. Если ваш последний вызов SmartHeap происходит до того, как ваше приложение будет готово к завершению, вы можете вызвать MemUnregisterTask для завершения работы SmartHeap.MemUnregisterTask уменьшает счетчик регистрационных ссылок на единицу — когда счетчик равен нулю, SmartHeap освобождает всю память, выделенную SmartHeap, и состояние отладки, связанное с текущей задачей или процессом.

16
задан Logan 26 April 2012 в 01:30
поделиться