Мой DLL-код работает из exe файла, но не загружается из Java loadLibrary - программирование
Подтвердить что ты не робот

Мой DLL-код работает из exe файла, но не загружается из Java loadLibrary

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

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

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

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

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


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

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


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


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

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

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

4b9b3361

Ответ 1

Что-нибудь полезное в файле журнала hs_err.... Обычно есть обратная трассировка стека и т.д. указывая на что-то.

Также попытался запустить java.exe(с параметрами, запускающими тест, который загружает материал) внутри отладчик?

Из вышеприведенного трассировки видно, что загрузка, кажется, работает нормально (вывод трассировки подсказывает что dllentrypoint/dllmain был дополнен вами/трассировкой на вас).

Последовательность в загрузке следующая:

  • зависимые от нагрузки dll
  • загрузить dll
  • вызов dllentrypoint/dllmain w/process attach

Таким образом, это уже загружает DLL.

Вы проверили, используете ли вы время отладки/выпуска в Windows? Отладка может конфликтовать с выпуском - Java - релиз, ваш пример exe, вероятно, был таким же, как и для вашей сборки dll.

Ответ 2

Похож на соглашение о вызове или несоответствие размера шрифта для меня. Каждый компилятор Windows C имеет свой собственный набор особенностей, а заголовки JNI Windows предполагают (недавнюю версию) Microsoft Visual С++. Посмотрите внимательно на предупреждения - потеря точности - это плохой знак.

Например, __int64 является специфичным для MSVC. Вам нужно узнать, что такое имя 64-разрядного целочисленного типа в Borland C и сопоставить его с __int64, прежде чем включать jni.h.