Aby System.loadLibrary()
biblioteka (w systemie Windows, DLL) działała, musi znajdować się w katalogu gdzieś na twoim komputerze PATH
lub na ścieżce wymienionej we java.library.path
właściwości systemowej (abyś mógł uruchomić Javę java -Djava.library.path=/path/to/dir
).
Dodatkowo w przypadku loadLibrary()
określasz nazwę podstawową biblioteki, bez .dll
końcówki. Więc po /path/to/something.dll
prostu używałbyś System.loadLibrary("something")
.
Musisz także dokładnie przyjrzeć się temu UnsatisfiedLinkError
, co otrzymujesz. Jeśli mówi coś takiego:
Exception in thread "main" java.lang.UnsatisfiedLinkError: no foo in java.library.path
wtedy nie może znaleźć biblioteki foo (foo.dll) w twoim PATH
lub java.library.path
. Jeśli mówi coś takiego:
Exception in thread "main" java.lang.UnsatisfiedLinkError: com.example.program.ClassName.foo()V
wtedy coś jest nie tak z samą biblioteką w tym sensie, że Java nie jest w stanie odwzorować natywnej funkcji Java w twojej aplikacji na jej rzeczywisty natywny odpowiednik.
Na początek umieściłbym trochę rejestrowania twojego System.loadLibrary()
wywołania, aby sprawdzić, czy działa poprawnie. Jeśli zgłosi wyjątek lub nie znajduje się w ścieżce kodu, która jest faktycznie wykonywana, zawsze otrzymasz ten drugi typ UnsatisfiedLinkError
wyjaśniony powyżej.
Na marginesie, większość ludzi umieszcza swoje loadLibrary()
wywołania w statycznym bloku inicjalizatora w klasie z metodami natywnymi, aby upewnić się, że jest on wykonywany zawsze dokładnie raz:
class Foo {
static {
System.loadLibrary('foo');
}
public Foo() {
}
}
loadLibrary()
uwagi - bardzo przydatne, gdy nie masz pojęcia, co robisz źle.lib
prefiksu. WięcSystem.loadLibrary("foo")
potrzebujelibfoo.so
.blah.jnilib
i Linuxlibblah.so
. Cóż, dwie godziny później, po wielu próbach, doszedłem do wniosku, że OSX również wymagalib
prefiksuZmiana zmiennej „java.library.path” w czasie wykonywania nie wystarczy, ponieważ jest ona odczytywana tylko raz przez maszynę JVM. Musisz to zresetować jak:
System.setProperty("java.library.path", path); //set sys_paths to null final Field sysPathsField = ClassLoader.class.getDeclaredField("sys_paths"); sysPathsField.setAccessible(true); sysPathsField.set(null, null);
Zdobądź łup w: Changing Java Library Path at Runtime .
źródło
Oryginalna odpowiedź Adama Batkina doprowadzi Cię do rozwiązania, ale jeśli ponownie wdrożysz aplikację internetową (bez ponownego uruchamiania kontenera internetowego), powinieneś napotkać następujący błąd:
java.lang.UnsatisfiedLinkError: Native Library "foo" already loaded in another classloader at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1715) at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1646) at java.lang.Runtime.load0(Runtime.java:787) at java.lang.System.load(System.java:1022)
Dzieje się tak, ponieważ ClassLoader, który pierwotnie załadował bibliotekę DLL, nadal odwołuje się do tej biblioteki DLL. Jednak Twoja aplikacja internetowa działa teraz z nowym ClassLoaderem, a ponieważ ta sama JVM jest uruchomiona, a JVM nie zezwala na 2 odwołania do tej samej biblioteki DLL, nie możesz jej ponownie załadować . Dlatego Twoja aplikacja internetowa nie może uzyskać dostępu do istniejącej biblioteki DLL i nie może załadować nowej. Więc ... utknęłaś.
Dokumentacja Tomcat ClassLoader przedstawia, dlaczego ponownie załadowana aplikacja internetowa działa w nowej, izolowanej aplikacji ClassLoader i jak można obejść to ograniczenie (na bardzo wysokim poziomie).
Rozwiązaniem jest niewielkie rozszerzenie rozwiązania Adama Batkina:
package awesome; public class Foo { static { System.loadLibrary('foo'); } // required to work with JDK 6 and JDK 7 public static void main(String[] args) { } }
Następnie umieść jar zawierający TYLKO tę skompilowaną klasę w folderze TOMCAT_HOME / lib.
Teraz w aplikacji internetowej wystarczy zmusić Tomcat do odwoływania się do tej klasy, co można zrobić tak prosto:
Class.forName("awesome.Foo");
Teraz Twoja biblioteka DLL powinna zostać załadowana do wspólnego modułu ładującego klasy i można do niej odwoływać się z aplikacji internetowej nawet po ponownym wdrożeniu.
Ma sens?
Roboczą kopię referencyjną można znaleźć w google code, static-dll-bootstrapper .
źródło
Możesz użyć,
System.load()
aby podać bezwzględną ścieżkę, która jest tym, czego chcesz, zamiast pliku w folderze biblioteki standardowej dla odpowiedniego systemu operacyjnego.Jeśli potrzebujesz natywnych aplikacji, które już istnieją, użyj
System.loadLibrary(String filename)
. Jeśli chcesz udostępnić własne, prawdopodobnie lepiej będzie z load ().Powinieneś także umieć poprawnie korzystać
loadLibrary
zjava.library.path
zestawu. ZobaczClassLoader.java
źródło implementacji pokazujące obie sprawdzane ścieżki (OpenJDK)źródło
W przypadku, gdy problem polega na tym, że System.loadLibrary nie może znaleźć danej biblioteki DLL, jednym z powszechnych nieporozumień (potwierdzonych komunikatem o błędzie języka Java) jest to, że odpowiedzią jest właściwość systemowa java.library.path. Jeśli ustawisz właściwość systemową java.library.path na katalog, w którym znajduje się biblioteka DLL, wówczas System.loadLibrary rzeczywiście znajdzie tę bibliotekę DLL. Jeśli jednak biblioteka DLL jest z kolei zależna od innych bibliotek DLL, co często się zdarza, java.library.path nie może pomóc, ponieważ ładowaniem zależnych bibliotek DLL zarządza w całości system operacyjny, który nic nie wie o java.library. ścieżka. Dlatego prawie zawsze lepiej jest ominąć java.library.path i po prostu dodać katalog biblioteki DLL do LD_LIBRARY_PATH (Linux), DYLD_LIBRARY_PATH (MacOS) lub Path (Windows) przed uruchomieniem JVM.
(Uwaga: używam terminu „DLL” w ogólnym znaczeniu biblioteki DLL lub biblioteki współdzielonej).
źródło
Jeśli chcesz załadować plik, który jest powiązany z katalogiem, w którym już jesteś (np. W bieżącym katalogu), oto proste rozwiązanie:
File f; if (System.getProperty("sun.arch.data.model").equals("32")) { // 32-bit JVM f = new File("mylibfile32.so"); } else { // 64-bit JVM f = new File("mylibfile64.so"); } System.load(f.getAbsolutePath());
źródło
Dla szukających
java.lang.UnsatisfiedLinkError: no pdf_java in java.library.path
Miałem ten sam wyjątek; Próbowałem wszystkiego, a ważne rzeczy, aby to działało, to:
To działało z tomcat 6.
źródło
Jeśli uważasz, że dodałeś ścieżkę natywnej biblioteki do
%PATH%
, spróbuj przetestować z:System.out.println(System.getProperty("java.library.path"))
Powinien pokazać ci, czy twoja dll jest włączona
%PATH%
%PATH%
źródło
Biedny ja ! spędził za tym cały dzień, zapisując to tutaj, jeśli ktoś powiela ten problem.
Próbowałem załadować, jak zasugerował Adam, ale potem złapałem wyjątek AMD64 vs IA 32.Jeśli w jakimkolwiek przypadku po pracy zgodnie z instrukcją Adama (bez wątpienia najlepszym wyborem), spróbuj mieć 64-bitową wersję najnowszego jre. twoje JRE i JDK są 64-bitowe i poprawnie dodałeś je do swojej ścieżki klas.
Oto mój przykład roboczy: błąd niezadowolonego linku
źródło
W przypadku systemu Windows stwierdziłem, że po załadowaniu plików filles (wywołania jd2xsx.dll & ftd2xx.dll) do folderu windowws / system32 rozwiązało to problemy. Wtedy miałem problem z moim nowszym fd2xx.dll związanym z parametrami, dlatego musiałem załadować starszą wersję tej biblioteki dll. Będę musiał to później przerobić.
Uwaga: jd2xsx.dll wywołuje ftd2xx.dll, więc samo ustawienie ścieżki do jd2xx.dll może nie działać.
źródło
Używam Mac OS X Yosemite i Netbeans 8.02, mam ten sam błąd, a proste rozwiązanie, które znalazłem, jest takie jak powyżej, jest to przydatne, gdy potrzebujesz włączyć natywną bibliotekę do projektu. Zrób więc następną dla Netbeans:
1.- Right click on the Project 2.- Properties 3.- Click on RUN 4.- VM Options: java -Djava.library.path="your_path" 5.- for example in my case: java -Djava.library.path=</Users/Lexynux/NetBeansProjects/NAO/libs> 6.- Ok
Mam nadzieję, że komuś się przyda. Link gdzie znalazłem rozwiązanie jest tutaj: java.library.path - co to jest i jak z niego korzystać
źródło
VM Options: java -Djava.library.path="your_path"
Miałem ten sam problem i błąd był spowodowany zmianą nazwy dll. Może się zdarzyć, że nazwa biblioteki jest również zapisana gdzieś w dll. Kiedy przywróciłem jego pierwotną nazwę, mogłem załadować za pomocą
System.loadLibrary
źródło
To proste, wystarczy napisać java -XshowSettings: properties w wierszu poleceń w systemie Windows, a następnie wkleić wszystkie pliki w ścieżce pokazanej przez java.library.path.
źródło
Najpierw upewnij się, że katalog Twojej biblioteki natywnej znajduje się w katalogu
java.library.path
. Zobacz, jak to zrobić tutaj . Następnie możesz zadzwonićSystem.loadLibrary(nativeLibraryNameWithoutExtension)
- uważając, aby nie dodawać rozszerzenia pliku w nazwie biblioteki.źródło