วิธีแก้ไข Uns SatisfiedLinkError (ไม่พบไลบรารีที่อ้างอิง) ในโครงการ JNI


86

ฉันกำลังทำงานกับโปรเจ็กต์ Java ที่ใช้ JNI JNI เรียกไลบรารีแบบกำหนดเองที่ฉันเขียนขึ้นเองสมมติว่า mylib.dll และขึ้นอยู่กับไลบรารีของบุคคลที่สาม libsndfile-1.dll

เมื่อฉันเรียกใช้โปรแกรมของฉันมันขัดข้องด้วย

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

ฉันได้ค้นหาไซต์นี้ (และอื่น ๆ ) และฉันได้ลองแก้ไขหลายอย่าง:

  1. ฉันวิ่งวอล์คเกอร์แบบพึ่งพา DW ให้คำเตือนสองสามไลบรารีสองไลบรารีที่ libsndfile ต้องการ MPR.DLL และ SHLWAPI.DLL มี "การนำเข้าที่ไม่ได้รับการแก้ไข" - แต่คำถามที่พบบ่อยของ DWกล่าวว่าคำเตือนเหล่านี้สามารถละเว้นได้อย่างปลอดภัย

  2. ฉันคงชื่อวิธีการใน MYLIB.dll ตามที่แนะนำที่นี่ ชื่อเมธอดถูกคอมไพเลอร์ยุ่งเหยิง แต่ฉันเพิ่มแฟล็ก linker และตอนนี้ชื่อเมธอด dll ตรงกับชื่อในไฟล์ส่วนหัว jni ของฉันทุกประการ

  3. ฉันใส่ DLL เหล่านี้ทั้งหมดไว้ในไดเร็กทอรีเดียวกัน - ไดเร็กทอรีเดียวกับ. jar ที่เรียกใช้ - เพื่อให้แน่ใจว่าอยู่ใน PATH ที่ถูกต้อง

ไม่มีลูกเต๋า

ใครมีความคิดว่าเกิดอะไรขึ้น?

ฉันกำลังพัฒนา Visual Studio 2010 บน MacBook pro (ผ่าน Parallels) ฉันกำลังทำการทดสอบใน Windows XP บนแล็ปท็อป toshiba


1
คุณได้ตั้งค่า -Djava.library.path หรือไม่
Jochen Bedersdorfer

ฉันไม่ได้เป็นเพราะฉันไม่ได้เปิดโปรแกรมจากบรรทัดคำสั่ง ฉันกำลังเขียนไลบรารีสำหรับการประมวลผล (processing.org) และการประมวลผลมีหน้าที่เปิดโค้ดของฉัน ฉันได้ตรวจสอบเส้นทางไลบรารี java ที่รันไทม์แล้วและโฟลเดอร์ที่มี DLL ของฉันอยู่ในนั้น
dB '23

อย่างที่บอกไปว่า DLL ทั้งหมดอยู่ในโฟลเดอร์เดียวกันถัดจากไฟล์. jar ของฉัน ดังนั้นฉันไม่คิดว่าปัญหาคือพวกเขาไม่ได้อยู่บนเส้นทาง แต่ยังไงก็ขอบคุณ
dB '23

7
ใน Windows เราต้องใส่ไฟล์. dll ในไดเร็กทอรี [JRE] \ bin (ที่เดียวกับที่ java.exe เป็นต้น) เพื่อให้ Java เห็นโดยอัตโนมัติโดยไม่ต้องยุ่งกับตัวเลือกบรรทัดคำสั่งหรือตัวแปรสภาพแวดล้อม
QuantumMechanic

4
อืม ... โอเคฉันลองใส่. dlls ทั้งหมดใน [JRE] \ bin แล้ว ได้ผล!
dB '23

คำตอบ:


52

ฉันค่อนข้างมั่นใจว่า classpath และเส้นทางการค้นหาไลบรารีที่แชร์มีส่วนเกี่ยวข้องกันเล็กน้อย ตามJNI Book (ซึ่งเป็นที่ยอมรับว่าเก่าแล้ว) บน Windows หากคุณไม่ได้ใช้java.library.pathคุณสมบัติระบบ DLL จะต้องอยู่ในไดเร็กทอรีการทำงานปัจจุบันหรือในไดเร็กทอรีที่แสดงอยู่ในPATHตัวแปรสภาพแวดล้อมของWindows


อัปเดต:

ดูเหมือนว่า Oracle ได้ลบ PDF ออกจากเว็บไซต์แล้ว ฉันได้อัปเดตลิงก์ด้านบนเพื่อชี้ไปที่ตัวอย่างของ PDF ที่อาศัยอยู่ที่ University of Texas - Arlington

นอกจากนี้คุณยังสามารถอ่าน HTML รุ่นของออราเคิลของJNI ข้อมูลจำเพาะ ที่อาศัยอยู่ในส่วน Java 8 ของเว็บไซต์ Java และหวังว่าจะอยู่ได้สักพัก


อัปเดต 2:

อย่างน้อยใน Java 8 (ฉันยังไม่ได้ตรวจสอบเวอร์ชันก่อนหน้านี้) คุณสามารถทำได้:

java -XshowSettings:properties -version

เพื่อค้นหาเส้นทางการค้นหาไลบรารีที่ใช้ร่วมกัน มองหาค่าของjava.library.pathคุณสมบัติในเอาต์พุตนั้น


2
ใช่CLASSPATHไม่ได้ใช้เลย ฉันไม่แน่ใจว่าcwdมีการใช้งานทั้งหมดหรือไม่ java.library.pathหรือPATHจะทำงาน @dB' สถานที่ที่คุณได้มีพวกเขาในขณะนี้คือผิด
Ernest Friedman-Hill

ขอบคุณมากครับ! ฉันคิดว่าส่วนหนึ่งของปัญหาที่นี่คือความสับสนในส่วนของฉันระหว่างตัวแปรสภาพแวดล้อม Windows PATH, java.library.path และ java CLASSPATH ทุกอย่างเข้าท่ากว่าตอนนี้
dB '23

โปรดอธิบายว่าคุณเอาชนะปัญหานี้ได้อย่างไร
SL_User

5
@SL_User ฉันคิดว่าถ้าคุณเพิ่มไดเร็กทอรีที่ไลบรารีอยู่ในตัวแปรสภาพแวดล้อม "path" และรีสตาร์ทพรอมต์คำสั่งหรือเทอร์มินัลควรแก้ไข Java ค้นหา jars ภายใต้ classpath และไลบรารีภายใต้ path
xxjjnn

1
จากคำตอบนี้ดูเหมือนว่าคำสั่งสำหรับอัปเดต 2 จะพร้อมใช้งานตั้งแต่อย่างน้อย Java 7: stackoverflow.com/a/8472139/901641
ArtOfWarfare

18

ฉันต้องการแจ้งกรณีที่น่าสนใจนี้หลังจากลองใช้วิธีการทั้งหมดข้างต้นแล้วข้อผิดพลาดยังคงอยู่ สิ่งที่แปลกคือมันทำงานบนคอมพิวเตอร์ Windows 7 แต่บน Windows XP นั้นไม่ได้ จากนั้นฉันใช้วอล์กเกอร์การพึ่งพาและพบว่าใน Windows XP ไม่มี VC ++ Runtime ตามความต้องการ dll ของฉัน หลังจากติดตั้งแพคเกจ VC ++ Runtime ที่นี่มันใช้งานได้อย่างมีเสน่ห์ สิ่งที่รบกวนฉันคือมันบอกอยู่เรื่อย ๆ ไม่พบไลบรารีที่พึ่งพาในขณะที่โดยสัญชาตญาณ dll ที่ขึ้นกับ JNI อยู่ที่นั่นอย่างไรก็ตามในที่สุดก็ปรากฎว่า dll ที่ขึ้นกับ JNI ต้องการ dl ที่ขึ้นอยู่กับอื่น ฉันหวังว่านี่จะช่วยได้.


4
ข้อความถูกต้องแม้ว่าในกรณีนี้จะทำให้เข้าใจผิด ฉันมีทั้ง VC ++ runtimes ที่หายไปในกล่องทดสอบและไลบรารีที่คอมไพล์ในโหมดดีบัก (ขึ้นอยู่กับรันไทม์ดีบักที่ไม่สามารถแจกจ่ายได้) Dependency Walkerเป็นตัวช่วยที่ดีในการคิดออก
Johnny Baloney

มีปัญหาเดียวกันกับการใช้ jnetpcap-library ไม่ได้ติดตั้ง winpcap แบบพึ่งพาบนเครื่องอีกต่อไปและข้อความข้อยกเว้นทำให้เข้าใจผิด
BlackFlag

ฉันคิดว่านี่อาจเป็นกรณีของฉัน
I.Tyger

ทุกวันนี้วอล์คเกอร์แบบพึ่งพากำลังได้รับความ "ยาวในฟัน" มันไม่สามารถเปิด dll windows 10/64 บิตล่าสุดได้เลยดังนั้นฉันยังไม่รู้ว่าไลบรารีใดหายไป ...
Mark Storer

15

คุณต้องโหลดไลบรารี JNI ของคุณ

System.loadLibraryโหลด DLL จากเส้นทาง JVM (เส้นทางถังขยะ JDK)

หากคุณต้องการโหลดไฟล์ที่ชัดเจนด้วยพา ธ ให้ใช้System.load ()

ดูเพิ่มเติม: ความแตกต่างระหว่าง System.load () และ System.loadLibrary ใน Java


5

โปรดตรวจสอบเส้นทางห้องสมุดของคุณว่าถูกต้องหรือไม่ แน่นอนคุณสามารถใช้รหัสต่อไปนี้เพื่อตรวจสอบเส้นทางห้องสมุดของคุณ: System.out.println(System.getProperty("java.library.path"));

คุณสามารถกำหนดjava.library.pathเมื่อเรียกใช้แอ็พพลิเคชัน Java:

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

4

หากคุณโหลด dll เวอร์ชัน 32 บิตด้วย JRE 64 บิตคุณอาจมีปัญหานี้ นี่เป็นกรณีของฉัน


นี่เป็นกรณีของฉันมากที่สุด หากมีใครทราบวิธีแก้ปัญหาที่ทราบแล้วฉันจะสนใจ ยกเว้นการโหลดเวอร์ชัน 64 บิตเนื่องจากในกรณีนี้กระบวนการไม่ใช่ dll แต่chromedriver.exeเป็นไดรเวอร์ Selenium สำหรับ Chrome ซึ่งเท่าที่ฉันบอกได้มาในเวอร์ชัน 32 บิตเท่านั้น
SantiBailors

4

มีปัญหาเหมือนกันกับบนเครื่อง XP เมื่อติดตั้งjavacvและopencvใช้ร่วมกับ Eclipse ปรากฎว่าฉันไม่มีไฟล์ต่อไปนี้:

  • msvcp100.dll
  • msvcr100.dll

เมื่อติดตั้งแล้วโครงการจะคอมไพล์และรัน OK


ฉันมีปัญหาที่คล้ายกันซึ่งหายไปหลังจากติดตั้ง "Microsoft Visual C ++ 2010 SP1 Redistributable Package (x86)"
Kirill Mikhailov

2
  • คำตอบสั้น ๆ : สำหรับข้อผิดพลาด "ไม่พบไลบรารีที่อ้างอิง" ให้ตรวจสอบ $ PATH ของคุณ (ตรงกับหัวข้อย่อย # 3 ด้านล่าง)
  • คำตอบยาว:
    1. Pure java world: jvm ใช้ "Classpath" เพื่อค้นหาไฟล์คลาส
    2. โลก JNI (ขอบเขตจาวา / เนทีฟ): jvm ใช้ "java.library.path" (ซึ่งมีค่าเริ่มต้นเป็น $ PATH) เพื่อค้นหา dlls
    3. pure native world: Native code ใช้ $ PATH เพื่อโหลด dll อื่น ๆ

2

ฉันพบบทความดีๆจากเพื่อนบางคนที่ร้านเซฟตี้ซึ่งผ่านสิ่งเดียวกับที่ฉันทำ มันใช้ได้ผลสำหรับฉันดังนั้นหวังว่ามันจะช่วยคุณได้เช่นกัน! อ่านหากคุณสนใจ ( The Perils of Loading Native Libraries บน Android ) หรือเพียงแค่ใช้

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

และแทนที่

System.loadLibrary("myLibrary");

ด้วย

ReLinker.loadLibrary(context, "mylibrary");

1

ฉันเคยมีปัญหาเดียวกันทุกประการและในที่สุดก็แก้ไขได้

ฉันใส่ DLL ที่ขึ้นอยู่กับทั้งหมดลงในโฟลเดอร์เดียวกันกับที่เก็บ mylib.dll และตรวจสอบให้แน่ใจว่า JAVA Compiler สามารถค้นหาได้ (หากไม่มี mylib.dll ในเส้นทางการคอมไพล์จะมีข้อผิดพลาดในการรายงานสิ่งนี้ในระหว่างการคอมไพล์) สิ่งสำคัญที่คุณต้องสังเกตคือคุณต้องตรวจสอบให้แน่ใจว่า libs ที่อ้างอิงทั้งหมดเป็นเวอร์ชันเดียวกันกับ mylib.dll ตัวอย่างเช่นหาก mylib.dll ของคุณเป็นเวอร์ชันวางจำหน่ายคุณควรใส่ libs ที่ขึ้นอยู่กับเวอร์ชันที่วางจำหน่ายไว้ที่นั่นด้วย .

หวังว่านี่จะช่วยผู้อื่นที่ประสบปัญหาเดียวกันได้


1

ฉันมีปัญหาเดียวกันและฉันพยายามทุกอย่างที่โพสต์ไว้ที่นี่เพื่อแก้ไข แต่ไม่มีอะไรได้ผลสำหรับฉัน ในกรณีของฉันฉันใช้ Cygwin เพื่อรวบรวม dll ดูเหมือนว่า JVM พยายามค้นหา JRE DLL ในเส้นทาง Cygwin เสมือน ฉันเพิ่มพา ธ ไดเร็กทอรีเสมือนของ Cygwin ไปยัง DLL ของ JRE และใช้งานได้ทันที ฉันทำสิ่งที่ชอบ:

SET PATH = "/ cygdrive / c / ไฟล์โปรแกรม / Java / jdk1.8.0_45";% PATH%


1

ในสถานการณ์ของฉันฉันพยายามเรียกใช้บริการเว็บจาวาใน Tomcat 7 ผ่านตัวเชื่อมต่อใน Eclipse แอปทำงานได้ดีเมื่อฉันปรับใช้ไฟล์สงครามกับอินสแตนซ์ของ Tomcat 7 บนแล็ปท็อปของฉัน แอปต้องการไดรเวอร์ jdbc type 2 สำหรับ "IBM DB2 9.5" ด้วยเหตุผลแปลก ๆ ตัวเชื่อมต่อใน Eclispe ไม่สามารถมองเห็นหรือใช้พา ธ ในตัวแปรสภาพแวดล้อม IBM DB2 เพื่อเข้าถึงไฟล์ dll ที่ติดตั้งบนแล็ปท็อปของฉันเป็นไคลเอ็นต์ jcc ข้อความแสดงข้อผิดพลาดระบุว่าไม่พบไฟล์ db2jcct2 dll หรือไม่พบไลบรารีที่อ้างอิงสำหรับไฟล์ dll นั้น ในที่สุดฉันก็ลบตัวเชื่อมต่อและสร้างใหม่ จากนั้นก็ทำงานได้อย่างถูกต้อง ฉันกำลังเพิ่มโซลูชันนี้ที่นี่เป็นเอกสารเนื่องจากฉันไม่พบโซลูชันเฉพาะนี้จากที่อื่น


0

การสร้างไลบรารีแบบคงที่ใช้งานได้สำหรับฉันการรวบรวมโดยใช้g++ -static. มันรวมไลบรารีที่ขึ้นต่อกันพร้อมกับบิลด์



0

วาง dll ที่ต้องการในโฟลเดอร์และตั้งค่าเส้นทางโฟลเดอร์ในตัวแปรสภาพแวดล้อม PATH ตรวจสอบให้แน่ใจว่าตัวแปร PATH สภาพแวดล้อมที่อัปเดตนั้นสะท้อนให้เห็น


0

ฉันประสบปัญหาเดียวกันกับห้องสมุด ffmpeg หลังจากรวมโครงการ Android สองโครงการเป็นโครงการเดียว

ปัญหาที่เกิดขึ้นจริงมาถึงเนื่องจากไลบรารี ffmpeg สองเวอร์ชันที่แตกต่างกัน แต่ถูกโหลดด้วยชื่อเดียวกันในหน่วยความจำ ไลบรารีหนึ่งถูกวางไว้ใน JNiLibs ในขณะที่ไลบรารีอื่นอยู่ในไลบรารีอื่นที่ใช้เป็นโมดูล ฉันไม่สามารถแก้ไขรหัสของโมดูลได้เนื่องจากเป็นแบบอ่านอย่างเดียวดังนั้นฉันจึงเปลี่ยนชื่อรหัสที่ใช้ในรหัสของฉันเองเป็น ffmpegCameraและโหลดไว้ในหน่วยความจำด้วยชื่อเดียวกัน

System.loadLibrary("ffmpegCamera");

วิธีนี้ช่วยแก้ปัญหาได้และขณะนี้ไลบรารีทั้งสองเวอร์ชันกำลังโหลดรวมทั้งชื่อและรหัสกระบวนการแยกต่างหากในหน่วยความจำ


0

เมื่อโทรSystem.loadLibrary()JVM จะดูที่ไฟล์java.library.pathไลบรารีดั้งเดิมของคุณ อย่างไรก็ตามหากไลบรารีเนทีฟนั้นประกาศการอ้างอิงใด ๆ กับไลบรารีเนทีฟอื่นระบบปฏิบัติการจะได้รับมอบหมายให้ค้นหาการอ้างอิงไลบรารีเนทีฟเหล่านั้น

เนื่องจากระบบปฏิบัติการไม่มีแนวคิดในเรื่องjava.library.pathนี้จึงไม่เห็นไดเร็กทอรีใด ๆ ที่คุณวางไว้บน java.library.path แต่จะค้นหาไดเร็กทอรีบนตัวแปรสภาพแวดล้อม PATH ของระบบปฏิบัติการเท่านั้น นี่เป็นสิ่งที่ดีโดยสิ้นเชิงหากการพึ่งพาไลบรารีเนทีฟเป็นไลบรารีเนทีฟของระบบปฏิบัติการเนื่องจากจะพบได้ใน PATH อย่างไรก็ตามหากการพึ่งพาไลบรารีเนทีฟเป็นไลบรารีเนทีฟที่คุณหรือผู้อื่นสร้างขึ้นจะไม่พบไลบรารีบน PATH เว้นแต่คุณจะวางไว้ที่นั่น พฤติกรรมนี้แปลกไม่คาดคิดและไม่ได้รับการบันทึกไว้อย่างดี แต่มีการบันทึกไว้ในเครื่องมือติดตามปัญหา OpenJDK ที่นี่ที่นี่นอกจากนี้คุณยังสามารถหาคำตอบ StackOverflow อื่นเสริมคำอธิบายนี้ที่นี่

ดังนั้นคุณมีสองตัวเลือก คุณสามารถโหลดไลบรารีเนทีฟแต่ละไลบรารีตามลำดับการอ้างอิงที่ถูกต้องโดยใช้System.loadLibrary()หรือคุณสามารถแก้ไข PATH เพื่อรวมไดเร็กทอรีที่จัดเก็บไลบรารีเนทีฟของคุณ


-2
  1. ไปที่http://tess4j.sourceforge.net/usage.htmlและคลิกที่Visual C++ Redistributable for VS2012
  2. ดาวน์โหลดและเรียกใช้VSU_4\vcredist_x64.exeหรือVSU_4\vcredist_x84.exeขึ้นอยู่กับการกำหนดค่าระบบของคุณ
  3. วางdllไฟล์ของคุณไว้ในlibโฟลเดอร์พร้อมกับไลบรารีอื่น ๆ ของคุณ (เช่น\lib\win32-x86\your dll files)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.