Bir JNI projesinde UnsatisfiedLinkError (bağımlı kitaplıklar bulunamıyor) nasıl düzeltilir


85

JNI kullanan bir Java projesi üzerinde çalışıyorum. JNI, kendi yazdığım özel bir kitaplığı çağırıyor, diyelim ki mylib.dll ve bu, libsndfile-1.dll adlı üçüncü taraf kitaplığına bağlı.

Programımı çalıştırdığımda çöküyor

java.lang.UnsatisfiedLinkError:  C:\...path...\mylib.dll: Can't find dependent libraries.

Bu siteyi (ve diğerlerini) araştırdım ve bir dizi düzeltmeyi denedim:

  1. Bağımlılık gezgini koştum. DW birkaç uyarı verdi - libsndfile, MPR.DLL ve SHLWAPI.DLL için gerekli olan iki kitaplığın "çözümlenmemiş içe aktarmalar" olduğu - ancak DW SSS bu uyarıların güvenli bir şekilde göz ardı edilebileceğini söyledi.

  2. Mylib.dll'deki yöntem adlarını burada önerildiği gibi düzelttim . Yöntem adları derleyici tarafından bir şekilde karıştırılmıştı, ancak bağlayıcı bayrakları ekledim ve dll yöntem adları artık jni başlık dosyamdakilerle tam olarak eşleşiyor.

  3. Tüm bu DLL'leri aynı dizine - onları çağıran .jar ile aynı dizine - doğru PATH'de olduklarından emin olmak için koydum.

Nafile.

Neler olduğu hakkında bir fikri olan var mı?

Bir MacBook pro üzerinde (Parallels aracılığıyla) Visual Studio 2010'da geliştirmemi yapıyorum. Testimi bir toshiba dizüstü bilgisayarda Windows XP'de yapıyorum.


1
-Djava.library.path ayarladınız mı?
Jochen Bedersdorfer

Aslında yapmadım çünkü programı komut satırından başlatmıyorum. Processing (processing.org) için bir kitaplık yazıyorum ve Processing, kodumu başlatmaktan sorumlu. Yine de çalışma zamanında java kütüphanesi yolunu kontrol ettim ve DLL'lerimi içeren klasör üzerinde.
dB '

Dediğim gibi, tüm DLL'ler aynı klasörde .jar dosyamın yanında. Bu yüzden sorunun yolda olmamaları olduğunu sanmıyorum. Yinede teşekkürler.
dB '

7
Windows'ta, Java'nın komut satırı seçenekleri veya ortam değişkenleriyle karıştırmak zorunda kalmadan bunları otomatik olarak görmesini sağlamak için .dll dosyalarını [JRE] \ bin dizinine (java.exe, vb. Olduğu yer) koymak zorunda kaldık.
QuantumMechanic

4
Hmm ... tamam, tüm .dll'lerimi [JRE] \ bin içine koymayı denedim. Bu çalışıyor!
dB '

Yanıtlar:


52

Eminim sınıf yolu ve paylaşılan kitaplık arama yolunun birbiriyle çok az ilgisi vardır. Göre JNI'yı Kitabı kullanmak yoksa (kuşkusuz eski), Windows üzerinde java.library.pathsistem özelliği, DLL ihtiyaçları geçerli çalışma dizini veya Windows listelenen bir dizinde olmasını PATHortam değişkeni.


Güncelleme:

Görünüşe göre Oracle PDF'yi web sitesinden kaldırmış. Texas Üniversitesi - Arlington'da yaşayan bir PDF örneğini işaret etmek için yukarıdaki bağlantıyı güncelledim.

Ayrıca, Oracle'ın HTML sürümünü de okuyabilirsiniz. JNI Spesifikasyonunun . Bu, Java web sitesinin Java 8 bölümünde yaşıyor ve umarım bir süre daha buralarda olur.


Güncelleme 2:

En azından Java 8'de (önceki sürümleri kontrol etmedim) şunları yapabilirsiniz:

java -XshowSettings:properties -version

paylaşılan kitaplık arama yolunu bulmak için. java.library.pathBu çıktıdaki özelliğin değerini arayın .


2
Evet, CLASSPATHhiç kullanılmıyor. Ben de cwdkullanıldığından emin değilim . java.library.pathveya basitçe PATHçalışacaktır. @dB ', onları şu anda aldığınız yer yanlış .
Ernest Friedman-Hill

Çok teşekkürler beyler! Sanırım buradaki sorunun bir kısmı, Windows PATH ortam değişkeni, java.library.path ve java CLASSPATH arasındaki benim açımdan bir karışıklıktı. Şimdi her şey daha mantıklı.
dB '

Lütfen bu sorunu nasıl aştığınızı açıklar mısınız?
SL_User

5
@SL_User Bence kütüphanelerin bulunduğu dizini "yol" ortam değişkenine eklerseniz ve komut istemini veya terminali yeniden başlatırsanız düzeltmesi gerekir. Java, sınıf yolu altındaki kavanozları ve yol altındaki kitaplıkları arar.
xxjjnn

1
Bu yanıta göre, Güncelleştirme 2 komutunun en az Java 7'den beri mevcut olduğu
görülüyor

18

Bu ilginç durumu bilgilendirmek istiyorum, yukarıdaki tüm yöntemleri denedikten sonra hata hala var. Garip olan şey, bir Windows 7 bilgisayarında çalışması, ancak Windows XP'de çalışmaması. Daha sonra bağımlılık yürüteçini kullanıyorum ve Windows XP'de dll gereksinimim olarak VC ++ Runtime olmadığını gördüm. VC ++ Runtime paketini buraya yükledikten sonra bir çekicilik gibi çalışır. Beni rahatsız eden şey, sezgisel olarak JNI bağımlı dll var iken, bağımlı kitaplıkları bulamıyorum, ancak sonunda JNI bağımlı dll'nin başka bir bağımlı dl gerektirdiğini söylemeye devam etmesi. Umarım bu yardımcı olur.


4
Mesaj bu durumda yanıltıcı olsa da doğrudur. Ben (bağlı testi kutusu ve ayıklama modunda derlenmiş kütüphaneye eksik hem VC ++ çalıştırıcıları vardı olmayan -redistributable ayıklama çalıştırıcıları). Dependency Walker , bunu çözmede çok yardımcı oldu.
Johnny Baloney

jnetpcap-library kullanarak aynı sorunu yaşadı. bağımlılık winpcap artık makinede kurulu değildi ve istisna mesajı yanıltıcıydı
BlackFlag

Bunun benim durumum olabileceğini düşünüyorum.
I. Tyger

Bu günlerde, bağımlılık yürüteçleri "dişleri uzuyor". Yeni bir Windows 10/64-bit dll'yi hiç açamadı, bu yüzden hala hangi kütüphanenin eksik olduğu hakkında hiçbir fikrim yok ... Whee.
Mark Storer


5

Lütfen kütüphane yolunuzun doğru olup olmadığını doğrulayın. Elbette, kütüphane yolunuzu kontrol etmek için aşağıdaki kodu kullanabilirsiniz: System.out.println(System.getProperty("java.library.path"));

Atayabilirsiniz Bir Java uygulamasını başlatırken java.library.path'i :

java -Djava.library.path=path ...

4

Eğer dll'nizin 32 bit sürümünü 64 bit JRE ile yüklerseniz bu sorunla karşılaşabilirsiniz. Bu benim davamdı.


Bu da büyük olasılıkla benim durumum; birisi bilinen geçici çözümlerin farkındaysa ilgilenirim; 64 bit sürümü yükleme dışında, bu durumda işlem bir dll değil chromedriver.exe, Chrome için Selenium sürücüsü, anlayabildiğim kadarıyla sadece 32 bit sürümde geliyor.
SantiBailors

4

Eclipse ile birlikte kurulurken javacvve birlikte kullanıldığında XP makinesinde de aynı problem vardı opencv. Aşağıdaki dosyaların eksik olduğu ortaya çıktı:

  • msvcp100.dll
  • msvcr100.dll

Bunlar kurulduktan sonra proje derlendi ve tamamlandı.


"Microsoft Visual C ++ 2010 SP1 Yeniden Dağıtılabilir Paketi (x86)" yükledikten sonra ortadan kaybolan benzer bir sorun yaşıyorum
Kirill Mikhailov

2
  • Kısa yanıt: "bağımlı kitaplık bulunamıyor" hatası için, $ PATH'nizi kontrol edin (aşağıdaki 3. madde noktasına karşılık gelir)
  • Uzun cevap:
    1. Saf java dünyası: jvm, sınıf dosyalarını bulmak için "Classpath" kullanır
    2. JNI dünyası (java / yerel sınır): jvm, dll'leri bulmak için "java.library.path" (varsayılan olarak $ PATH şeklindedir) kullanır
    3. saf yerel dünya: yerel kod, diğer dll'leri yüklemek için $ PATH kullanır

2

Keepafe'de bazı arkadaşlarımın benim yaptığımla aynı şeyi anlatan harika bir makalesi buldum. Benim için çalıştı, umarım sana da yardımcı olur! İlginizi çekiyorsa ( Android'de Yerel Kitaplıkları Yüklemenin Tehlikeleri ) veya yalnızca

compile 'com.getkeepsafe.relinker:relinker:1.2.3'

ve değiştir

System.loadLibrary("myLibrary");

ile

ReLinker.loadLibrary(context, "mylibrary");

1

Eskiden tamamen aynı sorunu yaşıyordum ve sonunda çözüldü.

Tüm bağımlı DLL'leri mylib.dll'nin depolandığı aynı klasöre koydum ve JAVA Derleyicisinin onu bulabileceğinden emin oldum (derleme yolunda mylib.dll yoksa, derleme sırasında bunu bildiren bir hata olurdu). Dikkat etmeniz gereken önemli şey, tüm bağımlı lib'lerin mylib.dll ile aynı sürümde olduğundan emin olmanız gerektiğidir, örneğin, mylib.dll'niz yayın sürümü ise, o zaman tüm bağımlı kitaplıkların yayın sürümünü de oraya koymalısınız. .

Umarım bu, aynı sorunla karşılaşan başkalarına yardımcı olabilir.


1

Aynı sorunu yaşadım ve düzeltmek için burada yayınlanan her şeyi denedim ama hiçbiri benim için işe yaramadı. Benim durumumda, dll'yi derlemek için Cygwin kullanıyorum. Görünüşe göre JVM, sanal Cygwin yolunda JRE DLL'lerini bulmaya çalışıyor. Cygwin'in sanal dizin yolunu JRE'nin DLL'lerine ekledim ve şimdi çalışıyor. Şöyle bir şey yaptım:

SET PATH = "/ cygdrive / c / Program Files / Java / jdk1.8.0_45";% PATH%


1

Benim durumumda, Eclipse'deki bir bağlayıcı aracılığıyla Tomcat 7'de bir java web hizmeti çalıştırmaya çalışıyordum. Savaş dosyasını dizüstü bilgisayarımdaki bir Tomcat 7 örneğine yerleştirdiğimde uygulama iyi çalıştı. Uygulama, "IBM DB2 9.5" için bir jdbc tip 2 sürücüsü gerektirir. Bazı garip nedenlerden dolayı Eclispe'deki bağlayıcı, jcc istemcisi olarak dizüstü bilgisayarıma kurulan dll dosyalarına erişmek için IBM DB2 ortam değişkenlerindeki yolları göremedi veya kullanamadı. Hata mesajı ya db2jcct2 dll dosyasını bulamadığını ya da bu dll dosyası için bağımlı kitaplıkları bulamadığını belirtti. Sonunda konektörü sildim ve yeniden oluşturdum. Sonra düzgün çalıştı. Bu çözümü buraya dokümantasyon olarak ekliyorum çünkü bu özel çözümü başka hiçbir yerde bulamadım.


0

Statik kitaplık oluşturmak benim için çalıştı g++ -static,. Bağımlı kitaplıkları yapı ile birlikte paketler.


0

Microsoft Visual C ++ 2010 SP1 Yeniden Dağıtılabilir'i yükleme Düzeltildi


0

gerekli dll'leri klasöre yerleştirin ve PATH ortam değişkeninde klasör yolunu ayarlayın. güncellenmiş ortam PATH değişkeninin yansıtıldığından emin olun.


0

İki Android projesini tek bir proje olarak birleştirdikten sonra ffmpeg kitaplığı ile aynı sorunla karşılaşıyordum.

Aslında sorun, ffmpeg kitaplığının iki farklı sürümü nedeniyle geliyordu, ancak bellekte aynı isimlerle yüklenmişlerdi. Bir kütüphane JNiLibs'e, diğeri ise modül olarak kullanılan başka bir kütüphaneye yerleştirildi. Modülün kodunu salt okunur olduğu için değiştiremedim, bu yüzden kendi kodumda kullanılanı ffmpegCamera olarak yeniden adlandırdım ve aynı adla belleğe yükledim .

System.loadLibrary("ffmpegCamera");

Bu, sorunu çözdü ve artık kitaplıkların her iki sürümü de bellekte ayrı ad ve işlem kimliği ile yükleniyor.


0

System.loadLibrary()JVM, arama yaparken java.library.pathyerel kitaplığınızı arayacaktır . Ancak, bu yerel kitaplık diğer yerel kitaplıklara herhangi bir bağımlılık bildirirse, işletim sistemine bu yerel kitaplık bağımlılıklarını bulma görevi verilecektir.

İşletim sistemi kavramı java.library.patholmadığından, java.library.path üzerine yerleştirdiğiniz hiçbir dizini görmeyecektir. Bunun yerine, yalnızca işletim sisteminin PATH ortam değişkenindeki dizinleri arayacaktır. Yerel kitaplık bağımlılığı bir işletim sistemi yerel kitaplığı ise bu tamamen iyidir çünkü PATH üzerinde bulunacaktır. Ancak, yerel kitaplık bağımlılığı sizin veya başka birinin oluşturduğu yerel bir kitaplıksa, siz onu oraya yerleştirmedikçe PATH üzerinde bulunmayacaktır. Bu davranış iyi belgelenmiş, tuhaf, beklenmedik ve değil, ama OpenJDK sorun izleyicide belgelenmiştir burada . Bu açıklamayı güçlendiren başka bir StackOverflow cevabını burada da bulabilirsiniz .

Yani, birkaç seçeneğiniz var. Her yerel kitaplığı kullanarak doğru bağımlılık sırasına göre yükleyebilir System.loadLibrary()veya PATH'yi yerel kitaplıklarınızın depolandığı dizinleri içerecek şekilde değiştirebilirsiniz.


-2
  1. Git http://tess4j.sourceforge.net/usage.html ve tıklayınVisual C++ Redistributable for VS2012
  2. İndirin ve çalıştırın VSU_4\vcredist_x64.exeveya VSU_4\vcredist_x84.exesistem yapılandırmanıza bağlı olarak
  3. dllDosyalarınızı libdiğer kitaplıklarınızla birlikte (örn. \lib\win32-x86\your dll files) Klasörün içine koyun .
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.