java.lang.UnsatisfiedLinkError no *****. dll, java.library.path içinde


92

Web uygulamama nasıl özel bir dll dosyası yükleyebilirim? Aşağıdakileri denedim:

  • Gerekli tüm DLL dosyaları Kopyalanan system32klasördeki ve bunlardan yük birine çalıştı ServletyapıcıSystem.loadLibrary
  • Gerekli dll'leri tomcat_home/shared/libve içine kopyaladıtomcat_home/common/lib

Tüm bu dll'ler WEB-INF/libweb uygulamasında

Yanıtlar:


156

İçin için System.loadLibrary()işe, (Windows, bir DLL üzerine) kütüphane sizinle ilgili şu bir dizin yere olmalıdır PATH veya listelenen bir yolda java.library.path(sizin gibi Java'yı başlatmak böylece sistem özelliği java -Djava.library.path=/path/to/dir).

Ek olarak, loadLibrary()kitaplığın temel adını .dllsonunda belirtmeden belirtirsiniz . Yani, /path/to/something.dllsadece kullanacaksın System.loadLibrary("something").

Ayrıca aldığınız kesinliğe UnsatisfiedLinkErrorde bakmanız gerekir . Şöyle bir şey söylüyorsa:

Exception in thread "main" java.lang.UnsatisfiedLinkError: no foo in java.library.path

o zaman foo kitaplığını (foo.dll) PATHveya java.library.path. Şöyle bir şey söylüyorsa:

Exception in thread "main" java.lang.UnsatisfiedLinkError: com.example.program.ClassName.foo()V

o zaman Java'nın uygulamanızdaki yerel bir Java işlevini gerçek yerel karşılığı ile eşleyememesi anlamında kitaplığın kendisinde bir sorun vardır.

Başlangıç ​​olarak, System.loadLibrary()düzgün çalışıp çalışmadığını görmek için aramanızın etrafına biraz günlük kaydı koyardım. Bir istisna atarsa ​​veya gerçekte çalıştırılan bir kod yolunda değilse, her zaman UnsatisfiedLinkErroryukarıda açıklanan ikinci türü alırsınız .

Bir yan not olarak, çoğu insan loadLibrary()çağrılarını her zaman tam olarak bir kez çalıştırıldığından emin olmak için yerel yöntemlerle sınıfta bir statik başlatıcı bloğuna koyar :

class Foo {

    static {
        System.loadLibrary('foo');
    }

    public Foo() {
    }

}

1
Tüm dll'leri System32'ye koyarak ve System.loadLibrary'yi ("bir şey") kullanarak işe yaradı. Daha önce System.loadLibrary ("something.dll") yapıyordum. Neden tüm dll'leri WEB-INF'den yükleyemiyor? Sanırım tüm kavanozları varsayılan olarak yüklüyor. Bu
dll'leri

2
Açıklama için "bla.dll" yerine "bla" için loadLibrary()+1 - ne yaptığınızı bilmediğinizde çok kullanışlıdır.
MarnixKlooster ReinstateMonica

21
Sistemimde (Linux ve java7), bir liböneke ihtiyacım var . Yani System.loadLibrary("foo")ihtiyaçlar libfoo.so.
kristianlm

2
Teşekkürler. Windows için "PATH" dosyasını * .so dosyasına sahip klasörler içerecek şekilde güncellediğimde benim için çalıştı.
user613114

OSX'in gerekli olduğuna blah.jnilibve Linux'a yemin edebilirdim libblah.so. Pekala, iki saat sonra, sayısız denemeden sonra, OSX'in de libön ek gerektirdiği sonucuna vardım
Jovan Perovic

15

JVM tarafından yalnızca bir kez okunduğundan, çalışma zamanında 'java.library.path' değişkenini değiştirmek yeterli değildir. Bunu şu şekilde sıfırlamalısın:

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);

Lütfen şu adresten ganimet alın: Çalışma Zamanında Java Kitaplığı Yolunu Değiştirme .


10

Adam Batkin'in orijinal cevabı sizi bir çözüme götürecek, ancak web uygulamanızı yeniden konuşlandırırsanız (web kapsayıcınızı yeniden başlatmadan), aşağıdaki hatayla karşılaşmalısınız:

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)

Bunun nedeni, DLL'nizi orijinal olarak yükleyen ClassLoader'ın hala bu DLL'ye başvurmasıdır. Ancak, web uygulamanız artık yeni bir ClassLoader ile çalışıyor ve aynı JVM çalıştığı ve bir JVM aynı DLL için 2 referansa izin vermediği için onu yeniden yükleyemezsiniz . Bu nedenle, web uygulamanız mevcut DLL'ye erişemez ve yeni bir tane yükleyemez. Yani ... sıkıştın.

Tomcat'in ClassLoader belgeleri , yeniden yüklenen web uygulamanızın neden yeni, yalıtılmış bir ClassLoader'da çalıştığını ve bu sınırlamayı nasıl aşabileceğinizi (çok yüksek düzeyde) özetliyor.

Çözüm, Adam Batkin'in çözümünü biraz genişletmek:

   package awesome;

   public class Foo {

        static {
            System.loadLibrary('foo');
        }

        // required to work with JDK 6 and JDK 7
        public static void main(String[] args) {
        }

    }

Ardından, SADECE bu derlenmiş sınıfı içeren bir kavanozu TOMCAT_HOME / lib klasörüne yerleştirin.

Şimdi, web uygulamanızda, Tomcat'i bu sınıfa başvurmaya zorlamanız yeterlidir, bu da şu kadar basit bir şekilde yapılabilir:

  Class.forName("awesome.Foo");

Artık DLL dosyanızın ortak sınıf yükleyiciye yüklenmesi gerekir ve yeniden konuşlandırıldıktan sonra bile web uygulamanızdan referans alınabilir.

Mantıklı olmak?

Google kodunda, static-dll-bootstrapper'da bir çalışma referans kopyası bulunabilir .


1
Bu yanıt, uygulama sunucuları için mükemmeldir ve bu soruda boşa harcandığı için kendi sorusu olmalıdır.
JoshDM

8

System.load()İlgili işletim sistemi için standart kitaplık klasöründeki bir dosya yerine, istediğiniz tam bir yol sağlamak için kullanabilirsiniz .

Zaten var olan yerel uygulamaları istiyorsanız, kullanın System.loadLibrary(String filename). Kendinizinkini sağlamak istiyorsanız, muhtemelen load () ile daha iyi olursunuz.

Ayrıca kullanmak gerekir loadLibraryile java.library.pathdüzgün seti. ClassLoader.javaKontrol edilen her iki yolu da gösteren uygulama kaynağına bakın (OpenJDK)


Teşekkürler. Yük kullanmak aslında çok daha kolay ve sezgisel bir IMHO. Ne yaparsam yapayım loadLibrary çalışmıyor ...
Plankalkül

2
Bu çözüm, kendi yerel kitaplıklarını yükleyen kitaplıklar için çalışmaz.
Justin Skiles

7

Sorunun System.loadLibrary'nin söz konusu DLL'yi bulamaması durumunda, yaygın bir yanılgı (Java'nın hata mesajı ile pekiştirilir) java.library.path sistem özelliğinin yanıt olduğudur. Java.library.path sistem özelliğini DLL dosyanızın bulunduğu dizine ayarlarsanız, System.loadLibrary gerçekten DLL dosyanızı bulacaktır. Ancak, DLL dosyanız genellikle olduğu gibi diğer DLL'lere bağlıysa, java.library.path yardımcı olamaz, çünkü bağımlı DLL'lerin yüklenmesi tamamen java.library hakkında hiçbir şey bilmeyen işletim sistemi tarafından yönetilir. yol. Bu nedenle, JVM'yi başlatmadan önce java.library.path'i atlamak ve DLL dizininizi LD_LIBRARY_PATH (Linux), DYLD_LIBRARY_PATH (MacOS) veya Path'e (Windows) eklemek neredeyse her zaman daha iyidir.

(Not: "DLL" terimini DLL veya paylaşılan kitaplığın genel anlamında kullanıyorum.)


5

Halihazırda bulunduğunuz bir dizine (mevcut dizinde olduğu gibi) göre bir dosya yüklemeniz gerekiyorsa, işte kolay bir çözüm:

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());

4

Arayanlar için java.lang.UnsatisfiedLinkError: no pdf_java in java.library.path

Ben de aynı istisnayla karşı karşıyaydım; Çalışması için her şeyi denedim ve önemli şeyler:

  1. Pdf lib.jar'ın doğru sürümü (Benim durumumda, sunucu çalışma zamanında tutulan kavanozun sürümü yanlıştı)
  2. Bir klasör oluşturun ve pdflib kavanozunu içinde tutun ve klasörü PATH değişkeninize ekleyin

Tomcat 6 ile çalıştı.


3
  1. Bir yerel kitaplık yolu eklediğinizi düşünüyorsanız, %PATH%test etmeyi deneyin:

    System.out.println(System.getProperty("java.library.path"))
    

Aslında dll'nizin açık olup olmadığını göstermelidir %PATH%

  1. Env değişkenini ekleyerek kurduktan sonra benim için çalıştığı görünen IDE Fikrini yeniden başlatın. %PATH%

2

Yazık bana ! bunun arkasında bütün bir gün geçirdim. herhangi bir vücut bu konuyu kopyalarsa buraya yazmak.

Adam'ın önerdiği gibi yüklemeye çalışıyordum ama sonra AMD64'e karşı IA 32 istisnasına yakalandım. Adam'ın (şüphesiz en iyi seçim) çözümüne göre çalıştıktan sonra, en son jre'nin 64 bit sürümüne sahip olmaya çalışın. JRE VE JDK'nız 64 bittir ve sınıf yolunuza doğru şekilde eklediniz.

Çalışma örneğim buraya: tatminsiz bağlantı hatası


0

Windows için dolguları (jd2xsx.dll çağrıları & ftd2xx.dll) windowws / system32 klasörüne yüklediğimde bunun sorunları çözdüğünü buldum. Daha sonra yeni fd2xx.dll dosyamın parametrelerle ilgili bir sorun yaşadım, bu yüzden bu dll'nin eski sürümünü yüklemek zorunda kaldım. Bunu daha sonra açıklamam gerekecek.

Not: jd2xsx.dll, ftd2xx.dll'yi çağırdığından jd2xx.dll için yolu ayarlamak işe yaramayabilir.


0

Mac OS X Yosemite ve Netbeans 8.02 kullanıyorum, aynı hatayı aldım ve bulduğum basit çözüm yukarıdaki gibi, projeye yerel kitaplık eklemeniz gerektiğinde bu yararlıdır. Netbeans için bir sonrakini yapın:

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

Umarım birisi için yararlı olabilir. Çözümü bulduğum bağlantı burada: java.library.path - Nedir ve nasıl kullanılır


Merhaba Alex, Burada bir sorum var, eğer kütüphane yolu bu satırdaki yolda bir miktar boşluk içeriyorsa herhangi bir sorun var mıVM Options: java -Djava.library.path="your_path"
Lokesh Pandey

Mmm Geçen yıl Java ile çalışmıyorum, ancak çakışmalar görünebileceğinden , dosya yoluna boşluk eklemekten kaçınmanızı öneririm .
alexventuraio

0

Aynı sorunu yaşadım ve hata dll'nin yeniden adlandırılmasından kaynaklanıyordu. Kütüphane adı da dll içinde bir yere yazılabilir. Orijinal adını geri koyduğumda, şunu kullanarak yükleyebildimSystem.loadLibrary


0

Basittir, java -XshowSettings: özellikler komut satırınıza Windows'ta yazın ve ardından tüm dosyaları java.library.path tarafından gösterilen yola yapıştırın.


0

Öncelikle, yerel kitaplığınızın dizininin java.library.path. Bunu nasıl yapacağınızı buradan öğrenin . Ardından, System.loadLibrary(nativeLibraryNameWithoutExtension)dosya uzantısını kitaplığınızın adına eklemediğinizden emin olarak arayabilirsiniz .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.