Я создал модуль С++ для сборки в файл разделяемой библиотеки, а затем вызываю его из 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 память и состояние отладки, связанные с текущей задачей или процессом.