Utworzyłem moduł C++, aby utworzyć plik biblioteki współużytkowanej, a następnie wywołać go z poziomu Javy przy użyciu JNI.Mój kod dll działa z pliku exe, ale nie ładuje się z biblioteki Java loadLibrary
Mam 2 środowiska, Windows i Unix i mam program wykonywalny C++ oraz program Java, który właśnie rekompiluję dla każdego środowiska.
- Kiedy skompilować mój program tester.exe w Unix i uruchomić go za pomocą metod z mojej biblioteki (.so) to działa dobrze.
- Gdy kompiluję mój program Java w systemie Unix i ładuję moją bibliotekę (.so) za pomocą loadLibrary Java, to działa dobrze.
Gdy kompiluję mój program tester.exe w systemie Windows i uruchamiam go przy użyciu metod z mojej biblioteki (.dll), to działa dobrze. Podobnie jak wersja unix .
Kiedy kompiluję mój program Java w Windows i ładuję moją bibliotekę (.dll) z loadLibrary Java, to się nie powiedzie. Mówi Próba dostępu do nieprawidłowego adresu .
Nie mogę zrozumieć, dlaczego nie będzie działać z Java LoadLibrary podczas pracy w systemie Windows, ale działa wszędzie przy użyciu tego samego kodu. Jeśli opóźniam ładowanie zależnej biblioteki DLL, z której korzysta moja biblioteka, to moja biblioteka ładuje się w Javie, ale nie działa. Wiem, że istnieje specjalny kod, który powoduje problem z ładowaniem biblioteki Java przez java, ale nie mogę zrozumieć, dlaczego mój C++ exe nie ma problemu z tymi samymi metodami i bibliotekami.
Moja biblioteka dll ma jedną odsłoniętą metodę, która wywołuje 4 metody z niektórych istniejących bibliotek. Jeśli skomentuję te 4 metody, moja biblioteka dll ładuje się w Javie dobrze. Wiem, że to ma coś wspólnego z tymi metodami z biblioteki, do której prowadzi moja biblioteka DLL. Czy jest coś innego w tym, w jaki sposób Java widzi biblioteki zależne? Próbowałem najpierw ładować zależne biblioteki, ale jeden z ładowanych plików dll powoduje błąd rekursji i przepełnienie stosu.
Ktoś wie, jak obejść bibliotekę DLL, która powoduje przepełnienie stosu spowodowane błędem rekursji? Potrzebuję metod w nim, ale nie mogę załadować go z loadLibrary java.
Oto więcej informacji o plikach i faktycznym komunikacie o błędzie. Dodałem DllMain do mojego podstawowego pliku dll po prostu zobaczyć, co ładuje i kiedy. Jeśli skompiluję ten sam program (my_plain_dll_to_call_JNI_DLL) jako plik exe, wszystko działa poprawnie. Jeśli go skompiluję i załaduję z mojego programu java, to się stanie.
- myJavaProgram, po prostu wywołuje System.loadLibrary(), aby załadować podstawową .dll plik, który wywołuje metodę w moim innych dll, który zawiera kod JNI.
- my_plain_dll_to_call_JNI_DLL to dll, który utworzyłem, łącząc go z moim plikiem biblioteki DLL tylko po to, aby przetestować zależność. Po prostu wywołuje metodę z innej biblioteki dll, która wywołuje natywny kod, którego potrzebuję.
- my_JNI_DLL.ll to plik DLL połączony z istniejącymi bibliotekami programowania w języku C++ , które muszę uzyskać dostęp z JNI. Zawiera bezpośrednie wywołania metod w istniejących bibliotekach kodu źródłowego.
napisałem nazwę pliku Wyświetlanie tekstu na lewo od każdej linii, aby pokazać, co warstwa wykonanie jest.
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
Aktualizacja mam zawężony do problemu biblioteka zarządzania pamięcią, która jest połączona z inną biblioteką dll, z której korzysta mój program. Plik DLL, którego używa, jest sh33w32.dll, nazywa się SmartHeap i jest przez firmę o nazwie Microquil, jak sądzę. Mam wersję 3.3, a gdy Java LoadLibrary próbuje załadować dll, nie powiedzie się. Nie jestem pewien, co mogę zrobić, aby uchwyt Java ładowanie tej biblioteki. Musi mieć coś wspólnego z obszarem pamięci, do którego może mieć dostęp Java, w przeciwieństwie do tego, do których okien umożliwia dostęp exe. Exe nie ma problemu z biblioteką SmartHeap, ale Java nie pozwoli mi jej używać. Wszelkie pomysły lub doświadczenia dotyczące tego? Próbowałem usunąć połączoną bibliotekę, rekompilując inne biblioteki, ale normalnie działają normalne wywołania w kodzie.
Dodatkowe informacje Znaleziony funkcji, która jest w dll, że nie można załadować w java nazywa MemRegisterTask. To produkt SmartHeap firmy Microquill. Oto dokumentacja, którą znalazłem na temat tej funkcji. Myślę, że ta alokacja pamięci powoduje, że java nie może go załadować.
Narzędzie MemRegisterTask inicjuje bibliotekę SmartHeap. Na większości platform nie trzeba wywoływać funkcji MemRegisterTask, ponieważ SmartHeap zainicjuje się podczas pierwszego połączenia.
SmartHeap utrzymuje liczbę referencyjną rejestracji dla każdego zadania lub procesu. Za każdym razem, gdy wywołujesz funkcję MemRegisterTask, ta liczba odwołań jest zwiększana. Jeśli Twoje ostatnie połączenie z SmartHeap nastąpi przed zakończeniem twojej aplikacji, możesz zadzwonić do MemUnregisterTask, aby zakończyć SmartHeap. MemUnregisterTask zmniejsza liczbę odwołań do rejestracji o jeden - gdy liczba wynosi zero, SmartHeap zwolni pamięć przydzieloną przez SmartHeap i stan debugowania powiązany z bieżącym zadaniem lub procesem.
Może opublikowanie kodu pomoże ludziom zobaczyć więcej na ten temat. Tylko szybkie sprawdzenie: poprawnie ujawniasz swoją bibliotekę DLL na java (np .: http://java.sun.com/developer/onlineTraining/Programming/JDCBook/jniexamp.html#impl) – JScoobyCed
Nie jestem pewien, czy mogę publikować kod, ze względu na reguły pracy. Pracowałem nad każdym innym błędem JNI, na który natknąłem się, więc staram się zrozumieć pojęcia, aby zobaczyć, czy nie widzę powodu, dla którego to się nie udaje. Ujawniam metodę 1, którą mój program java używa poprawnie. Problem polega na tym, że biblioteka dll nie ładuje się nawet w systemie Windows Java, Unix Java działa dobrze. – Logan
Wygląda na to, że z komunikatu o wyjątku wynika, że albo parametry paramter do funkcji C++ są niepoprawne (zestawione w inny typ, niż oczekiwano), albo połączenie nie zostanie wykonane poprawnie. Możliwe, że biblioteka C++ została skompilowana z różnymi konwencjami wywołania niż to, co zapewnia/zakłada JNI. – Attila