Agar System.loadLibrary()
dapat berfungsi, pustaka (di Windows, DLL) harus berada di direktori di suatu tempat di Anda PATH
atau di jalur yang tercantum di java.library.path
properti sistem (sehingga Anda dapat meluncurkan seperti Java java -Djava.library.path=/path/to/dir
).
Selain itu, untuk loadLibrary()
, Anda menentukan nama dasar pustaka, tanpa .dll
akhiran. Jadi, untuk itu /path/to/something.dll
, Anda hanya akan menggunakan System.loadLibrary("something")
.
Anda juga perlu melihat persis apa UnsatisfiedLinkError
yang Anda peroleh. Jika tertulis sesuatu seperti:
Exception in thread "main" java.lang.UnsatisfiedLinkError: no foo in java.library.path
maka ia tidak dapat menemukan pustaka foo (foo.dll) di PATH
atau java.library.path
. Jika tertulis sesuatu seperti:
Exception in thread "main" java.lang.UnsatisfiedLinkError: com.example.program.ClassName.foo()V
maka ada yang salah dengan pustaka itu sendiri dalam arti bahwa Java tidak dapat memetakan fungsi Java asli dalam aplikasi Anda ke mitra aslinya yang sebenarnya.
Untuk memulainya, saya akan meletakkan beberapa logging di sekitar System.loadLibrary()
panggilan Anda untuk melihat apakah itu dijalankan dengan benar. Jika itu melontarkan pengecualian atau tidak dalam jalur kode yang benar-benar dieksekusi, maka Anda akan selalu mendapatkan jenis terakhir yang UnsatisfiedLinkError
dijelaskan di atas.
Sebagai catatan kecil, kebanyakan orang menempatkan loadLibrary()
panggilan mereka ke dalam blok penginisialisasi statis di kelas dengan metode asli, untuk memastikan bahwa itu selalu dieksekusi tepat sekali:
class Foo {
static {
System.loadLibrary('foo');
}
public Foo() {
}
}
loadLibrary()
komentar-- sangat berguna bila Anda tidak tahu apa yang Anda lakukan salah.lib
awalan. JadiSystem.loadLibrary("foo")
kebutuhanlibfoo.so
.blah.jnilib
dan Linuxlibblah.so
. Nah, dua jam kemudian, setelah beberapa kali mencoba, saya sampai pada kesimpulan bahwa OSX juga memerlukanlib
awalanMengubah variabel 'java.library.path' saat runtime tidak cukup karena hanya dibaca sekali oleh JVM. Anda harus mengatur ulang seperti:
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);
Silakan, ambil jarahan di: Mengubah Jalur Perpustakaan Java pada Waktu Proses .
sumber
Jawaban asli oleh Adam Batkin akan mengarahkan Anda ke solusi, tetapi jika Anda menerapkan ulang webapp Anda (tanpa memulai ulang penampung web Anda), Anda akan mengalami kesalahan berikut:
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)
Ini terjadi karena ClassLoader yang awalnya memuat DLL Anda masih mereferensikan DLL ini. Namun, aplikasi web Anda sekarang berjalan dengan ClassLoader baru, dan karena JVM yang sama sedang berjalan dan JVM tidak mengizinkan 2 referensi ke DLL yang sama, Anda tidak dapat memuatnya kembali. Jadi, aplikasi web Anda tidak dapat mengakses DLL yang ada dan tidak dapat memuat yang baru. Jadi .... Anda terjebak.
Dokumentasi ClassLoader Tomcat menguraikan mengapa aplikasi web Anda yang dimuat ulang berjalan di ClassLoader baru yang terisolasi dan bagaimana Anda dapat mengatasi batasan ini (pada tingkat yang sangat tinggi).
Solusinya adalah memperluas solusi Adam Batkin sedikit:
package awesome; public class Foo { static { System.loadLibrary('foo'); } // required to work with JDK 6 and JDK 7 public static void main(String[] args) { } }
Kemudian tempatkan jar yang berisi HANYA kelas yang dikompilasi ini ke dalam folder TOMCAT_HOME / lib.
Sekarang, di dalam aplikasi web Anda, Anda hanya perlu memaksa Tomcat untuk mereferensikan kelas ini, yang dapat dilakukan sesederhana ini:
Class.forName("awesome.Foo");
Sekarang DLL Anda harus dimuat di classloader umum, dan dapat dirujuk dari aplikasi web Anda bahkan setelah diterapkan ulang.
Masuk akal?
Salinan referensi kerja dapat ditemukan di kode google, static-dll-bootstrapper .
sumber
Anda dapat menggunakan
System.load()
untuk menyediakan jalur absolut yang Anda inginkan, daripada file dalam folder pustaka standar untuk masing-masing OS.Jika Anda menginginkan aplikasi asli yang sudah ada, gunakan
System.loadLibrary(String filename)
. Jika Anda ingin menyediakan milik Anda sendiri, Anda mungkin lebih baik menggunakan load ().Anda juga harus dapat menggunakan
loadLibrary
denganjava.library.path
set dengan benar. LihatClassLoader.java
sumber implementasi yang menunjukkan kedua jalur yang sedang diperiksa (OpenJDK)sumber
Dalam kasus di mana masalahnya adalah bahwa System.loadLibrary tidak dapat menemukan DLL yang dimaksud, satu kesalahpahaman umum (diperkuat oleh pesan kesalahan Java) adalah bahwa properti sistem java.library.path adalah jawabannya. Jika Anda menyetel properti sistem java.library.path ke direktori tempat DLL Anda berada, maka System.loadLibrary memang akan menemukan DLL Anda. Namun, jika DLL Anda bergantung pada DLL lain, seperti yang sering terjadi, java.library.path tidak dapat membantu, karena pemuatan DLL dependen dikelola sepenuhnya oleh sistem operasi, yang tidak mengetahui apa pun tentang java.library. jalan. Dengan demikian, hampir selalu lebih baik untuk melewati java.library.path dan cukup menambahkan direktori DLL Anda ke LD_LIBRARY_PATH (Linux), DYLD_LIBRARY_PATH (MacOS), atau Path (Windows) sebelum memulai JVM.
(Catatan: Saya menggunakan istilah "DLL" dalam pengertian umum DLL atau pustaka bersama.)
sumber
Jika Anda perlu memuat file yang terkait dengan beberapa direktori tempat Anda berada (seperti di direktori saat ini), berikut adalah solusi mudah:
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());
sumber
Bagi yang mencari
java.lang.UnsatisfiedLinkError: no pdf_java in java.library.path
Saya menghadapi pengecualian yang sama; Saya mencoba segalanya dan hal penting untuk membuatnya berhasil adalah:
Ini bekerja dengan tomcat 6.
sumber
Jika Anda yakin telah menambahkan jalur lib asli ke
%PATH%
, coba uji dengan:System.out.println(System.getProperty("java.library.path"))
Ini harus menunjukkan kepada Anda sebenarnya jika dll Anda aktif
%PATH%
%PATH%
sumber
Kasihan aku! menghabiskan sepanjang hari di belakang ini. Menuliskannya di sini jika ada orang yang mengulangi masalah ini.
Saya mencoba memuat seperti yang disarankan Adam tetapi kemudian tertangkap dengan pengecualian AMD64 vs IA 32. Jika bagaimanapun setelah bekerja sesuai panduan Adam (tidak diragukan lagi pilihan terbaik), cobalah untuk memiliki versi 64 bit jre terbaru. JRE DAN JDK Anda 64 bit dan Anda telah menambahkannya dengan benar ke classpath Anda.
Contoh kerja saya berjalan di sini: kesalahan tautan tidak puas
sumber
Untuk windows saya menemukan bahwa ketika saya memuat filles (panggilan jd2xsx.dll & ftd2xx.dll) ke dalam folder windowws / system32 ini menyelesaikan masalah. Saya kemudian memiliki masalah dengan fd2xx.dll saya yang lebih baru berkaitan dengan parameter itulah sebabnya saya harus memuat versi lama dll ini. Aku harus membicarakan ini nanti.
Catatan: jd2xsx.dll memanggil ftd2xx.dll jadi hanya mengatur jalur untuk jd2xx.dll mungkin tidak berfungsi.
sumber
Saya menggunakan Mac OS X Yosemite dan Netbeans 8.02, saya mendapat kesalahan yang sama dan solusi sederhana yang saya temukan adalah seperti di atas, ini berguna ketika Anda perlu menyertakan perpustakaan asli dalam proyek. Jadi lakukan selanjutnya untuk 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
Semoga bisa bermanfaat bagi seseorang. Tautan tempat saya menemukan solusinya ada di sini: java.library.path - Apa itu dan bagaimana cara menggunakannya
sumber
VM Options: java -Djava.library.path="your_path"
Saya memiliki masalah yang sama dan kesalahan itu karena mengganti nama dll. Bisa jadi nama perpustakaan juga ditulis di suatu tempat di dalam dll. Ketika saya mengembalikan nama aslinya, saya bisa memuat menggunakan
System.loadLibrary
sumber
Sangat sederhana, cukup tulis java -XshowSettings: properti pada baris perintah Anda di windows dan kemudian tempelkan semua file di jalur yang ditunjukkan oleh java.library.path.
sumber
Pertama, Anda ingin memastikan direktori ke perpustakaan asli Anda ada di
java.library.path
. Lihat bagaimana melakukannya di sini . Kemudian, Anda dapat meneleponSystem.loadLibrary(nativeLibraryNameWithoutExtension)
- pastikan untuk tidak menyertakan ekstensi file dalam nama perpustakaan Anda.sumber