2016-04-29 9 views
7

में लोड किया गया है मैंने एक वेब-एप्लिकेशन तैनात किया है, जिसमें निम्न कोड शामिल है।java.lang.UnsatisfiedLinkError: मूल पुस्तकालय XXX.so पहले से ही किसी अन्य क्लासलोडर

System.loadLibrary(org.opencv.core.Core.NATIVE_LIBRARY_NAME); 

अब, मैंने एक और वेब-एप्लिकेशन तैनात किया है जिसमें एक ही कोड है। जब यह लाइब्रेरी लोड करने का प्रयास करता है, तो यह निम्न त्रुटि फेंक देता है।

Exception in thread "Thread-143" java.lang.UnsatisfiedLinkError: 
Native Library /usr/lib/jni/libopencv_java248.so already loaded in 
another classloader 

मैं इन दोनों अनुप्रयोगों को एक साथ चलाने के लिए चाहता हूं।

    एक आवेदन में
  1. लोडेड पुस्तकालय और एक अन्य आवेदन में अपवाद ऊपर पकड़ा
  2. निकाला गया जार दोनों आवेदन से और opencv.jar (यानी/usr में बिलाव के classpath में डाल दिया:

    अब मैं क्या कोशिश की है जब तक

    /शेयर/tomcat7/lib)।

लेकिन ऊपर से कोई भी काम नहीं करता, कोई सुझाव जिसके द्वारा मैं यह कर सकता हूं?

संपादित करें: विकल्प दो के लिए,

System.loadLibrary(Core.NATIVE_LIBRARY_NAME); 

इस लाइन काम करता है लेकिन अपवाद है जब मैं वास्तव में है कि पुस्तकालय का उपयोग करने के लिए जा रहा हूँ हो जाता है। यही कारण है कि जब मैं

Mat mat = Highgui.imread("/tmp/abc.png"); 

निम्न उपाय अपनाते हैं और मैं इस अपवाद

java.lang.UnsatisfiedLinkError: org.opencv.highgui.Highgui.imread_1(Ljava/lang/String;)J 
    at org.opencv.highgui.Highgui.imread_1(Native Method) 
    at org.opencv.highgui.Highgui.imread(Highgui.java:362) 
+0

संख्या 2 काम करना चाहिए था। आप सुनिश्चित हैं कि आपने इसे कहीं और हटा दिया है और वेबपैप में कुछ अन्य जार नहीं है जो lib को लोड करने का प्रयास करता है? – user2543253

+0

@ user2543253 कृपया मेरे संपादित प्रश्न की जांच करें। –

+0

क्या आप जांच सकते हैं कि 'हाईगुई' उसी वर्ग लोडर द्वारा लोड किया गया है जो 'loadLibrary' करता है? अन्यथा मूल तरीकों को प्रारंभ नहीं किया जाता है। – user2543253

उत्तर

5

समस्या से कैसे OpenCV देशी पुस्तकालय का आरंभीकरण संभालती है मिलता है।

आमतौर पर एक क्लास जो मूल पुस्तकालय का उपयोग करता है, में एक स्थिर प्रारंभकर्ता होगा जो लाइब्रेरी को लोड करता है। इस तरह कक्षा और मूल पुस्तकालय हमेशा एक ही कक्षा लोडर में लोड किया जाएगा। ओपनसीवी के साथ एप्लिकेशन कोड मूल पुस्तकालय लोड करता है।

अब प्रतिबंध है कि मूल पुस्तकालय केवल एक वर्ग लोडर में लोड किया जा सकता है। वेब अनुप्रयोग अपने स्वयं के वर्ग लोडर का उपयोग करते हैं, इसलिए यदि एक वेब एप्लिकेशन ने मूल पुस्तकालय लोड किया है, तो दूसरा वेब एप्लिकेशन ऐसा नहीं कर सकता है। इसलिए देशी पुस्तकालयों को लोड करने वाले कोड को वेबैप निर्देशिका में नहीं रखा जा सकता है लेकिन कंटेनर (टॉमकैट) साझा निर्देशिका में रखा जाना चाहिए। जब आपके पास कक्षा के उपयोग के स्थिर प्रारंभकर्ता में उपरोक्त सामान्य पैटर्न (loadLibrary) के साथ लिखी गई कक्षा है, तो साझा निर्देशिका में कक्षा वाले जार को रखना पर्याप्त है। ओपनसीवी और loadLibrary वेब एप्लिकेशन कोड में कॉल के साथ, मूल पुस्तकालय अभी भी "गलत" वर्ग लोडर में लोड हो जाएगा और आपको UnsatisfiedLinkError मिल जाएगा।

"दाएं" वर्ग लोडर को देशी लाइब्रेरी लोड करने के लिए आप एक छोटी कक्षा बना सकते हैं जिसमें एक स्थिर विधि केवल loadLibrary कर सकती है। इस वर्ग को एक अतिरिक्त जार में रखें और इस जार को साझा टोमकैट निर्देशिका में रखें। फिर वेब अनुप्रयोगों में कॉल को आपकी नई स्थैतिक विधि पर कॉल के साथ System.loadLibrary पर प्रतिस्थापित करें। इस तरह ओपनसीवी कक्षाओं और उनकी मूल पुस्तकालय के लिए कक्षा लोडर मेल खाते हैं और मूल तरीकों को शुरू किया जा सकता है।

संपादित करें: उदाहरण के रूप में

public class WebApplicationClass { 
    static { 
     System.loadLibrary(org.opencv.core.Core.NATIVE_LIBRARY_NAME); 
    } 
} 

उपयोग

public class ToolClassInSeparateJarInSharedDirectory { 
    public static void loadNativeLibrary() { 
     System.loadLibrary(org.opencv.core.Core.NATIVE_LIBRARY_NAME); 
    } 
} 

public class WebApplicationClass { 
    static { 
     ToolClassInSeparateJarInSharedDirectory.loadNativeLibrary(); 
    } 
} 
-1

javacpp> = 1.3 आप भी कैश फ़ोल्डर बदल सकते हैं के रूप में की

बजाय एक टिप्पणीकार द्वारा अनुरोध (सिस्टम द्वारा परिभाषित किया गया संपत्ति) आपके युद्ध परिनियोजन श्रोता में:

System.setProperty("org.bytedeco.javacpp.cachedir", 
        Files.createTempDirectory("javacppnew").toString()); 

ध्यान दें कि मूल पुस्तकालय हमेशा अनपॅक किए जाते हैं और कई बार लोड किए जाएंगे (क्योंकि विभिन्न libs के रूप में माना जाता है)।

संबंधित मुद्दे