Możliwe jest utworzenie pojedynczego pliku JAR ze wszystkimi zależnościami, w tym z natywnymi bibliotekami JNI dla jednej lub większej liczby platform. Podstawowym mechanizmem jest użycie System.load (File) do załadowania biblioteki zamiast typowego System.loadLibrary (String), który przeszukuje właściwość systemową java.library.path. Ta metoda znacznie upraszcza instalację, ponieważ użytkownik nie musi instalować biblioteki JNI w swoim systemie, kosztem jednak, że wszystkie platformy mogą nie być obsługiwane, ponieważ konkretna biblioteka dla platformy może nie być zawarta w jednym pliku JAR .
Proces przebiega następująco:
- dołącz natywne biblioteki JNI do pliku JAR w lokalizacji specyficznej dla platformy, na przykład w NATIVE / $ {os.arch} / $ {os.name} /libname.lib
- utworzyć kod w statycznym inicjatorze klasy głównej do
- oblicz aktualny os.arch i os.name
- poszukaj biblioteki w pliku JAR w predefiniowanej lokalizacji za pomocą Class.getResource (String)
- jeśli istnieje, wyodrębnij go do pliku tymczasowego i załaduj za pomocą System.load (plik).
Dodałem funkcjonalność, aby to zrobić dla jzmq, powiązań Java ZeroMQ (bezwstydna wtyczka). Kod można znaleźć tutaj . Kod jzmq wykorzystuje rozwiązanie hybrydowe, więc jeśli nie można załadować wbudowanej biblioteki, kod powróci do wyszukiwania biblioteki JNI w java.library.path.
UnsatisfiedLinkError
ponieważ ładowanie poprzedniej biblioteki dll niejawnie chce załadować drugą, ale nie mogę jej znaleźć, ponieważ jest ukryta w słoiku. Również ładowanie tej ostatniej biblioteki dll w pierwszej kolejności nie pomaga.DLL
muszą być znane z wyprzedzeniem, a ich lokalizacje należy dodać doPATH
zmiennej środowiskowej.https://www.adamheinrich.com/blog/2012/12/how-to-load-native-jni-library-from-jar/
to świetny artykuł, który rozwiązuje mój problem.
W moim przypadku mam następujący kod do inicjalizacji biblioteki:
źródło
Spójrz na One-JAR . Spowoduje to umieszczenie aplikacji w jednym pliku jar z wyspecjalizowanym programem ładującym klasy, który obsługuje między innymi „pliki jar wewnątrz jars”.
To obsługuje natywne (JNI) bibliotek przez rozpakowanie je do tymczasowego folderu roboczego zgodnie z wymaganiami.
(Zastrzeżenie: nigdy nie używałem One-JAR, jeszcze nie musiałem, po prostu dodałem go do zakładek na deszczowy dzień.)
źródło
1) Dołącz bibliotekę natywną do pliku JAR jako zasób. Np. z Maven lub Gradle i standardowym układem projektu, umieść bibliotekę natywną w
main/resources
katalogu.2) Gdzieś w statycznych inicjalizatorach klas Javy, związanych z tą biblioteką, umieść kod w następujący sposób:
źródło
JarClassLoader to moduł ładujący klasy do ładowania klas, natywnych bibliotek i zasobów z pojedynczego potwora JAR oraz z JAR wewnątrz potwornego JAR.
źródło
Prawdopodobnie będziesz musiał rozpakować natywną bibliotekę do lokalnego systemu plików. O ile wiem, fragment kodu, który wykonuje natywne ładowanie, patrzy na system plików.
Ten kod powinien pomóc Ci zacząć (nie patrzyłem na niego od jakiegoś czasu i służy do innego celu, ale powinien załatwić sprawę, a ja jestem w tej chwili dość zajęty, ale jeśli masz pytania, zostaw komentarz i odpowiem najszybciej jak będę mógł).
źródło