जेएनआई परियोजना में एक असंतुष्टLinkError (आश्रित पुस्तकालयों को नहीं पा सकते) को कैसे ठीक करें


85

मैं एक जावा प्रोजेक्ट पर काम कर रहा हूं जो JNI का उपयोग करता है। JNI ने एक कस्टम लाइब्रेरी को कॉल किया है जिसे मैंने खुद लिखा है, मान लीजिए mylib.dll, और यह एक 3rd पार्टी लाइब्रेरी, libsndfile-1.dll पर निर्भर करता है।

जब मैं अपना प्रोग्राम चलाता हूं तो यह क्रैश हो जाता है

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

मैंने इस साइट (और अन्य) को खोज लिया है और मैंने कई सुधारों की कोशिश की है:

  1. मैंने डिपेंडेंसी वॉकर चलाया। DW ने कुछ चेतावनियाँ दीं - कि दो पुस्तकालयों के लिए आवश्यक libsndfile, MPR.DLL और SHLWAPI.DLL ने "अनसुलझे आयात" किए - लेकिन DW FAQ ने कहा कि इन चेतावनियों को सुरक्षित रूप से अनदेखा किया जा सकता है।

  2. मैंने यहाँ सुझाए अनुसार mylib.dll में विधि के नाम तय किए हैं । विधि के नाम किसी तरह कंपाइलर द्वारा मंगवा लिए गए थे, लेकिन मैंने लिंकर झंडे जोड़े और डीएल विधि के नाम अब मेरे जनी हेडर फ़ाइल में बिल्कुल मेल खाते हैं।

  3. मैंने इन सभी DLL को एक ही डायरेक्टरी में रखा है - एक ही डाइरेक्टरी जो .jar के रूप में है, जो उन्हें कॉल करती है - यह सुनिश्चित करने के लिए कि वे सही पेट पर हैं।

कोई पाँसा नहीं।

किसी को भी पता नहीं क्या चल रहा है?

मैं एक मैकबुक पर दृश्य स्टूडियो 2010 में अपना विकास कर रहा हूँ Pro (समानताएं के माध्यम से)। मैं एक toshiba लैपटॉप पर Windows XP में अपना परीक्षण कर रहा हूं।


1
क्या आपने सेट किया है -jj.library.path?
जोचेन बेडर्सडॉर्फ

मैं वास्तव में नहीं हूँ, क्योंकि मैं कमांड लाइन से प्रोग्राम लॉन्च नहीं कर रहा हूँ। मैं प्रोसेसिंग (प्रसंस्करण.ओआरजी) के लिए एक पुस्तकालय लिख रहा हूं, और प्रसंस्करण मेरे कोड को लॉन्च करने के लिए जिम्मेदार है। मैंने रनटाइम पर जावा लाइब्रेरी पथ की जाँच की है, और मेरा DLL युक्त फ़ोल्डर उस पर है।
dB

जैसा कि मैंने कहा, सभी DLL मेरे .jar फ़ाइल के बगल में एक ही फ़ोल्डर में हैं। इसलिए मुझे नहीं लगता कि समस्या यह है कि वे रास्ते पर नहीं हैं। लेकिन फिर भी धन्यवाद।
dB

7
विंडोज़ पर हमें .dll फ़ाइलों को [JRE] \ बिन निर्देशिका (उसी जगह जहाँ java.exe, आदि हैं) में जावा को कमांड लाइन विकल्प या पर्यावरण चर के साथ मिलाने के बिना स्वचालित रूप से देखने के लिए प्राप्त करना होगा।
क्वांटमचैनीक

4
हम्म ... ठीक है, मैंने अपने सभी .dlls [JRE] \ bin में डालने की कोशिश की। यह काम!
dB

जवाबों:


52

मुझे पूरा यकीन है कि क्लासपाथ और साझा पुस्तकालय खोज पथ एक दूसरे के साथ बहुत कम हैं। के अनुसार JNI बुक (जो बेशक पुरानी है), विंडोज पर अगर आप का उपयोग नहीं करते java.library.pathप्रणाली संपत्ति, DLL जरूरतों वर्तमान कार्यशील निर्देशिका में या Windows में सूचीबद्ध एक निर्देशिका में होना करने के लिए PATHवातावरण चर।


अपडेट करें:

ऐसा लगता है कि ओरेकल ने पीडीएफ को अपनी वेबसाइट से हटा दिया है। मैंने यूनिवर्सिटी ऑफ टेक्सास - आर्लिंगटन में रहने वाले पीडीएफ की एक आवृत्ति को इंगित करने के लिए ऊपर लिंक अपडेट किया है।

इसके अलावा, आप जेएनआई विनिर्देश के ओरेकल के HTML संस्करण को भी पढ़ सकते हैं । यह जावा वेबसाइट के जावा 8 अनुभाग में रहता है और इसलिए उम्मीद है कि यह थोड़ी देर के लिए होगा।


अपडेट 2:

कम से कम जावा 8 में (मैंने पहले के संस्करणों की जाँच नहीं की है) आप कर सकते हैं:

java -XshowSettings:properties -version

साझा लाइब्रेरी खोज पथ खोजने के लिए। java.library.pathउस आउटपुट में संपत्ति के मूल्य के लिए देखो ।


2
हाँ, CLASSPATHबिल्कुल उपयोग नहीं किया जाता है। मुझे यकीन नहीं है कि cwdइसका इस्तेमाल बिल्कुल भी किया जाता है। java.library.pathया बस PATHकाम करेगा। @dB ', जिस स्थान पर आप उन्हें प्राप्त कर चुके हैं, वह गलत है
अर्नेस्ट फ्रीडमैन-हिल

बहुत बहुत धन्यवाद दोस्तों! मुझे लगता है कि यहाँ समस्या का एक हिस्सा विंडोज पैठ पर्यावरण चर, java.library.path और जावा क्लासेथ के बीच मेरी उलझन थी। यह सब अब और अधिक समझ में आता है।
dB

कृपया आप बता सकते हैं कि आप इस समस्या से कैसे उबर पाए?
SL_User

5
@SL_User मुझे लगता है कि यदि आप उस निर्देशिका को जोड़ते हैं जहां पुस्तकालय पर्यावरण चर "पथ" पर हैं और कमांड प्रॉम्प्ट या टर्मिनल को पुनरारंभ करें तो इसे ठीक करना चाहिए। जावा क्लासपाथ के नीचे जार, और पुस्तकालयों को रास्ते के नीचे देखता है।
xxjjnn

1
इस उत्तर के आधार पर, ऐसा लगता है कि अपडेट 2 के लिए कमांड कम से कम जावा 7 से उपलब्ध है: stackoverflow.com/a/8472139/901641
ArtOfWarfare

18

मैं इस दिलचस्प मामले को सूचित करना चाहता हूं, उपरोक्त सभी विधि की कोशिश करने के बाद, त्रुटि अभी भी है। अजीब बात यह है कि यह विंडोज 7 कंप्यूटर पर काम करता है, लेकिन विंडोज एक्सपी पर यह नहीं है। फिर मैं निर्भरता वॉकर का उपयोग करता हूं और विंडोज एक्सपी पर पाया कि मेरी कुल आवश्यकता के रूप में कोई वीसी ++ रनटाइम नहीं है। VC ++ रनटाइम पैकेज को यहां स्थापित करने के बाद यह एक आकर्षण की तरह काम करता है। जो चीज मुझे परेशान करती है वह यह बताती रहती है कि आप आश्रित पुस्तकालयों को नहीं पा सकते हैं, जबकि सहज रूप से जेएनआई पर निर्भर डीएल है, हालांकि अंत में पता चलता है कि जेएनआई पर निर्भर डीएल को एक और आश्रित डीएल की आवश्यकता है। आशा है कि ये आपकी मदद करेगा।


4
संदेश इस मामले में भ्रामक है। मेरे पास दोनों वीसी ++ रनटाइम्स थे जो टेस्ट बॉक्स पर गायब थे और लाइब्रेरी को डिबग मोड ( गैर- अविश्वसनीय डिबग रनटाइम के आधार पर ) में संकलित किया गया था । डिपेंडेंसी वॉकर को यह पता लगाने में बहुत मदद मिली।
जॉनी बालोनी

jnetpcap- लाइब्रेरी का उपयोग करते हुए एक ही मुद्दा था। निर्भरता winpcap अब मशीन पर स्थापित नहीं किया गया था और अपवाद संदेश भ्रामक था
BlackFlag

im यह मेरा मामला हो सकता है।
१२

इन दिनों, निर्भरता वॉकर सुंदर "दांत में लंबा" हो रहा है। यह हाल ही में विंडोज़ 10/64-बिट dll बिल्कुल नहीं खोल सकता है, इसलिए मुझे अभी भी पता नहीं है कि कौन सी लाइब्रेरी गायब है ... क्रु।
मार्क स्टॉपर

14

आपको अपने जेएनआई पुस्तकालय को लोड करने की आवश्यकता है।

System.loadLibrary JLM पथ (JDK बिन पथ) से DLL लोड करता है।

यदि आप किसी पथ से स्पष्ट फ़ाइल लोड करना चाहते हैं, तो System.load () का उपयोग करें

इसे भी देखें: जावा में System.load () और System.loadLibrary के बीच अंतर


5

कृपया सत्यापित करें कि आपका पुस्तकालय पथ सही है या नहीं। बेशक, आप अपने पुस्तकालय पथ पथ की जांच करने के लिए निम्नलिखित कोड का उपयोग कर सकते हैं: System.out.println(System.getProperty("java.library.path"));

जावा एप्लिकेशन लॉन्च करते समय आप java.library.path को नियुक्त कर सकते हैं :

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

4

यदि आप 64 बिट JRE के साथ अपने dll का 32 बिट संस्करण लोड करते हैं, तो आपके पास यह समस्या हो सकती है। यह मेरा मामला था।


यह सबसे अधिक संभावना मेरा मामला भी है; अगर किसी को ज्ञात वर्कअराउंड के बारे में पता है तो मुझे दिलचस्पी होगी; 64 बिट संस्करण को लोड करने के अलावा, जैसा कि इस मामले में प्रक्रिया एक dll नहीं है chromedriver.exe, लेकिन क्रोम के लिए सेलेनियम ड्राइवर, जो कि जहां तक ​​मैं बता सकता हूं केवल 32 बिट संस्करण में आता है।
शांतिबेल

4

था XP मशीन जब स्थापित करने पर साथ समान समस्या है javacvऔर opencvग्रहण के साथ संयोजन में। यह पता चला कि मुझे निम्नलिखित फाइलें याद आ रही थीं:

  • msvcp100.dll
  • msvcr100.dll

एक बार ये स्थापित हो जाने के बाद, प्रोजेक्ट संकलित किया गया और ठीक चला गया।


मुझे ऐसी ही समस्या है जो "Microsoft Visual C ++ 2010 SP1 Redistributable Package (x86)" को स्थापित करने के बाद गायब हो जाती है
Kirill Mikhailov

2
  • संक्षिप्त उत्तर: "आश्रित पुस्तकालय नहीं पा सकता" त्रुटि के लिए, अपने $ PATH की जाँच करें (बुलेट बिंदु # 3 से नीचे)
  • लंबा जवाब:
    1. शुद्ध जावा दुनिया: jvm क्लास की फाइलों को खोजने के लिए "क्लासपाथ" का उपयोग करता है
    2. JNI दुनिया (जावा / देशी सीमा): jvm dll को खोजने के लिए "java.library.path" (जो $ PATH को चूकता है) का उपयोग करता है
    3. शुद्ध देशी दुनिया: अन्य dll को लोड करने के लिए देशी कोड $ PATH का उपयोग करता है

2

मुझे कुछ मित्रों द्वारा कीप कैफे में एक बेहतरीन लेख मिला जो उसी चीज से गुजरा जो मैंने किया था। यह मेरे लिए काम करता है, इसलिए उम्मीद है कि यह आपकी मदद करता है! यदि आप रुचि रखते हैं ( Android पर लोडिंग मूल पुस्तकालयों के खतरों ) या केवल उपयोग करें, तो पढ़ें

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

और प्रतिस्थापित करें

System.loadLibrary("myLibrary");

साथ में

ReLinker.loadLibrary(context, "mylibrary");

1

मुझे वास्तव में यही समस्या थी, और आखिरकार इसे हल कर दिया गया।

मैंने सभी निर्भर DLL को उसी फ़ोल्डर में रखा, जहाँ mylib.dll संग्रहीत था और सुनिश्चित करें कि JAVA कंपाइलर इसे पा सकता है (यदि संकलन पथ में कोई mylib.dll नहीं है, तो संकलन के दौरान यह रिपोर्ट करने में त्रुटि होगी)। आपको जिस महत्वपूर्ण चीज़ पर ध्यान देने की ज़रूरत है, वह यह है कि आप यह सुनिश्चित करें कि सभी निर्भर लिबास mylib.dll के साथ एक ही संस्करण के हैं, उदाहरण के लिए यदि आपका mylib.dll रिलीज़ संस्करण है, तो आपको अपने सभी निर्भर फ़िक्सेस का रिलीज़ संस्करण भी रखना चाहिए ।

आशा है कि यह उन लोगों की मदद कर सकता है जिन्होंने समान समस्या का सामना किया है।


1

मेरे पास एक ही मुद्दा था, और मैंने इसे ठीक करने के लिए यहां जो कुछ भी पोस्ट किया है, मैंने कोशिश की लेकिन किसी ने भी मेरे लिए काम नहीं किया। मेरे मामले में मैं dll संकलित करने के लिए Cygwin का उपयोग कर रहा हूं। ऐसा लगता है कि JVM JRE DLL को आभासी Cygwin पथ में खोजने की कोशिश करता है। मैंने JRE के DLL में Cygwin के वर्चुअल डाइरेक्टरी पथ को जोड़ा और यह अब काम करता है। मैंने कुछ इस तरह किया:

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


1

अपनी स्थिति में, मैं ग्रहण में एक कनेक्टर के माध्यम से टॉमकैट 7 में एक जावा वेब सेवा चलाने की कोशिश कर रहा था। जब मैंने अपने लैपटॉप पर टॉमकैट 7 के उदाहरण के लिए युद्ध फाइल को तैनात किया तो ऐप अच्छी तरह से चला। एप्लिकेशन को "IBM DB2 9.5" के लिए jdbc टाइप 2 ड्राइवर की आवश्यकता होती है। कुछ अजीब कारण के लिए Eclispe में कनेक्टर आईबीएम DB2 पर्यावरण चर में पथों का उपयोग नहीं कर सकता है या नहीं देख सकता है, जो कि मेरे लैपटॉप पर ज्ल क्लाइंट के रूप में स्थापित डीएल फाइलों तक पहुंच सकता है। त्रुटि संदेश या तो यह कहा गया कि यह db2jcct2 dll फ़ाइल को खोजने में विफल रहा है या यह उस dll फ़ाइल के लिए निर्भर पुस्तकालयों को खोजने में विफल रहा है। अंततः, मैंने कनेक्टर को हटा दिया और इसे फिर से बनाया। फिर ठीक से काम किया। मैं इस समाधान को दस्तावेज के रूप में यहां जोड़ रहा हूं, क्योंकि मैं इस विशिष्ट समाधान को कहीं और खोजने में विफल रहा।


0

स्थैतिक पुस्तकालय बनाना मेरे लिए काम कर रहा था, जिसका उपयोग करके संकलन किया गया g++ -static। यह बिल्ड के साथ आश्रित पुस्तकालयों को बंडल करता है।



0

फ़ोल्डर में आवश्यक dlls रखें और फ़ोल्डर पथ को PATH पर्यावरण चर में सेट करें। सुनिश्चित करें कि अद्यतन वातावरण PATH चर परिलक्षित होता है।


0

मैं एक ही परियोजना के रूप में दो Android परियोजनाओं के विलय के बाद ffmpeg पुस्तकालय के साथ एक ही मुद्दे का सामना कर रहा था।

वास्तव में मुद्दा ffmpeg लाइब्रेरी के दो अलग-अलग संस्करणों के कारण आ रहा था, लेकिन उन्हें मेमोरी में समान नामों से लोड किया गया था। एक लाइब्रेरी को JNiLibs में रखा गया था जबकि दूसरे को मॉड्यूल के रूप में इस्तेमाल की जाने वाली दूसरी लाइब्रेरी के अंदर रखा गया था। मैं मॉड्यूल के कोड को संशोधित करने में सक्षम नहीं था क्योंकि यह आसानी से था इसलिए मैंने अपने कोड में इस्तेमाल किए गए एक का नाम बदलकर ffmpegCamera किया और इसे उसी नाम से मेमोरी में लोड किया।

System.loadLibrary("ffmpegCamera");

इससे समस्या हल हो गई और अब पुस्तकालयों के दोनों संस्करण अलग-अलग नाम और मेमोरी में प्रोसेस आईडी लोड कर रहे हैं।


0

कॉल करते समय System.loadLibrary(), JVM java.library.pathआपके मूल पुस्तकालय की खोज करेगा। हालांकि, यदि वह मूल पुस्तकालय अन्य देशी पुस्तकालयों पर कोई निर्भरता की घोषणा करता है, तो ऑपरेटिंग सिस्टम को उन मूल पुस्तकालय आश्रितों को खोजने का काम सौंपा जाएगा।

चूंकि ऑपरेटिंग सिस्टम की कोई अवधारणा नहीं है java.library.path, इसलिए यह आपके द्वारा java.library.path पर कोई निर्देशिका नहीं देखेगा। इसके बजाय, यह केवल ऑपरेटिंग सिस्टम के PATH पर्यावरण चर पर निर्देशिकाओं को खोजेगा। यह पूरी तरह से ठीक है अगर देशी पुस्तकालय निर्भरता एक ऑपरेटिंग सिस्टम देशी पुस्तकालय है क्योंकि यह पीएटीएच पर पाया जाएगा। हालांकि, यदि मूल पुस्तकालय निर्भरता एक मूल पुस्तकालय है जिसे आपने या किसी और ने बनाया है, तो यह PATH पर नहीं मिलेगा जब तक कि आप इसे वहां नहीं डालते। यह व्यवहार अजीब, अप्रत्याशित है, और अच्छी तरह से प्रलेखित नहीं है, लेकिन यह OpenJDK मुद्दे पर नजर रखने वाले में यहां प्रलेखित है । आप इस स्पष्टीकरण को सुदृढ़ करने के लिए एक और StackOverflow उत्तर भी पा सकते हैं, यहाँ

तो, आपके पास कुछ विकल्प हैं। आप या तो प्रत्येक मूल पुस्तकालय को सही निर्भरता क्रम का उपयोग करके लोड System.loadLibrary()कर सकते हैं, या आप निर्देशिकाओं को शामिल करने के लिए पथ को संशोधित कर सकते हैं जहां आपके मूल पुस्तकालय संग्रहीत हैं।


-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) के साथ रखें।
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.