2011-09-20 13 views
7

मेरे पास एक ऐसा मामला है जहां मुझे अपने आवेदन में बहुत सारे क्लास लोडर बनाने की ज़रूरत है ताकि अस्थायी रूप से कुछ कोड दिखाई दे सकें जबकि उपयोगकर्ता द्वारा दी गई स्क्रिप्ट चल रही हों। मैं इसके लिए URLClassLoader का उपयोग कर रहा हूं और यह बहुत अच्छी तरह से काम करता है।मैं क्लासलोडर को "बंद" कैसे करूं?

जब स्क्रिप्ट समाप्त हो जाती है, तो मैं संसाधनों को मुक्त करने के लिए कक्षा लोडर को "अनलोड" या "बंद" करना चाहता हूं।

क्या कक्षा लोडर के संदर्भ को null पर संदर्भित करना पर्याप्त है? मैं विशेष रूप से सोच रहा हूं कि क्या मैं अंततः फाइल हैंडल से बाहर हो जाऊंगा क्योंकि अतिरिक्त कक्षाएं जेएआर फाइलों में हैं।

पीएस: जावा 5 और ऊपर के साथ काम करना चाहिए। हाँ, मुझे पता है ...

+0

इस उपयोगी हो सकता है // stackoverflow। कॉम/प्रश्न/148681/अनलोडिंग-क्लास-इन-जावा? – Thomas

+0

आप ऑब्जेक्ट संदर्भों को हटाना चाहते हैं या कक्षा को अनलोड करना चाहते हैं। तो आप ternured या permgen – ssedano

+0

के बारे में चिंतित हैं असल में, मैं खुले कनेक्शन के बारे में चिंतित हूं (यानी संसाधन लोड करने के लिए इनपुट इनपुट खोल दिया गया है)। –

उत्तर

4

जब कक्षा लोडर लोड किए गए सभी वर्गों में अब कोई संदर्भ नहीं है, और क्लास लोडर के सभी संदर्भों को मिटा दिया गया है, तो कक्षा लोडर और लोड किए गए वर्गों को समूह के रूप में एकत्रित कचरा होगा।

ध्यान दें कि यह JVM विशेषता सेट होने पर निर्भर है जो अप्रतिबंधित कक्षाओं को उतारने का कारण बनता है। यह अधिकांश वातावरण में डिफ़ॉल्ट रूप से सेट है, लेकिन कुछ एम्बेडेड मामलों में नहीं हो सकता है।

[ध्यान दें कि यह कक्षा के संदर्भों को हटाने के लिए एक गैर-मामूली मामला है। नाम से संदर्भित कोई भी अन्य वर्ग निश्चित रूप से हटाने को रोक देगा। तो वर्ग को क्लासलोडर.फिंड क्लास या कुछ इसी तरह का उपयोग करके लोड किया जाना चाहिए।]

+0

आप विशेषता जानते हैं? – home

+0

नहीं। यह अधिक अस्पष्ट लोगों में से एक है, और बाद के जेवीएम पर बाहरी नहीं किया जा सकता है। –

+0

यह सिक्का का एक पक्ष है। यदि मैं जार बदलता हूं जिसमें कक्षाएं हैं, तो एक नया क्लासलोडर बनाएं और सटीक उसी यूआरएल के माध्यम से लोड करें, क्या मुझे नई कक्षाएं मिलेंगी या क्या कैशिंग शामिल है? –

1

यूआरएल क्लास लोडर या उसके किसी भी मूल वर्ग में कोई करीबी() विधियां नहीं हैं, इसलिए आप भाग्य से बाहर हैं।

क्या जीसी इसे संभाल नहीं लेना चाहिए?

+0

सहमत हैं, बस अपने क्लासलोडर (इसके माता-पिता से विशेष रूप से) का संदर्भ देना बंद करें और इसे एकत्र किया जाएगा, इसकी कक्षाएं का पालन करेंगी। – Guillaume

+0

@ गुइलाइम - आसानी से नहीं किया गया। –

3

यदि आपके पास उस क्लासलोडर से कक्षाएं (और ऑब्जेक्ट) लोड नहीं है, और यदि आप उस क्लासलोडर के लिए कोई संदर्भ नहीं रखते हैं, तो यह स्वचालित रूप से कचरा कलेक्टर द्वारा संभाला जाएगा।

0

मैंने URLClassLoader बढ़ाया और जावा 7s के आधार पर एक करीबी विधि बनाई। मैं अपने आईपैड 2 पर अपने आईआरसी बॉट को विकसित करना चाहता था, इसलिए मैंने जो किया था, मैंने किया। अब मेरी प्लगइन प्रणाली जावा 6 और 7 पर स्थिर है, hurray।

+4

आपकी 'करीबी()' विधि क्या करती है? –

+0

(मैं शर्त लगा रहा हूं कि यह लोडर एकत्रित नहीं करता है।) –

5

थोड़ा देर हो चुकी है, लेकिन उम्मीद है कि यह उन लोगों के लिए उपयोगी होगा जो बाद में (मेरे जैसे) इस प्रश्न में आते हैं।

जावा 7 के साथ, close() विधि URLClassLoader में जोड़ा गया है, जो ठीक वही है जो ओपी पूछ रहा था।

संपादित (@Hot Licks करने के लिए धन्यवाद) : ठीक है, तो यह नहीं बिल्कुल क्या ओ पी के लिए कहा गया है। यह सभी संसाधनों को मुक्त नहीं करता है, या संसाधनों और लोडर को संग्रहित नहीं करता है। यह क्लास लोडर का उपयोग करके अधिक संसाधनों को लोड करने से रोकता है। यह है, हालांकि, URLClassLoader के साथ लोड की गई जार फ़ाइल को बंद करें।

+0

* बंद() * विधि लोडर और इसके संसाधन एकत्रित नहीं करती है, यह बस अधिक कक्षाओं के लोडिंग को रोकती है। –

+0

धन्यवाद। यकीन नहीं है कि मैं इसे कैसे चूक गया। हालांकि, यह जार फ़ाइल को बंद करने लगता है, जिसका अर्थ यह है कि अगर मैं सही ढंग से समझता हूं तो जार फ़ाइल को अब हटाया जा सकता है/संशोधित किया जा सकता है? –

+0

हां, इसका तात्पर्य है कि जार फाइलें बंद हैं। –

3

आप Java7 उपयोग नहीं कर सकते हैं और यह करीब() विधि है, उपयोग प्रतिबिंब एक classloader की सभी खुले जार अभिलेखागार बंद करने के लिए है, तो जैसे: http:

public void close() { 
try { 
    Class clazz = java.net.URLClassLoader.class; 
    java.lang.reflect.Field ucp = clazz.getDeclaredField("ucp"); 
    ucp.setAccessible(true); 
    Object sun_misc_URLClassPath = ucp.get(this); 
    java.lang.reflect.Field loaders = 
     sun_misc_URLClassPath.getClass().getDeclaredField("loaders"); 
    loaders.setAccessible(true); 
    Object java_util_Collection = loaders.get(sun_misc_URLClassPath); 
    for (Object sun_misc_URLClassPath_JarLoader : 
     ((java.util.Collection) java_util_Collection).toArray()) { 
     try { 
     java.lang.reflect.Field loader = 
      sun_misc_URLClassPath_JarLoader.getClass().getDeclaredField("jar"); 
     loader.setAccessible(true); 
     Object java_util_jar_JarFile = 
      loader.get(sun_misc_URLClassPath_JarLoader); 
     ((java.util.jar.JarFile) java_util_jar_JarFile).close(); 
     } catch (Throwable t) { 
     // if we got this far, this is probably not a JAR loader so skip it 
     } 
    } 
} catch (Throwable t) { 
    // probably not a SUN VM 
} 
return; 
} 
+0

के अनुसार संपादित किया है, मैं जावा 1.6 का उपयोग कर रहा हूं, मैंने URLCassloader को साफ़ करने के लिए पूर्ण जीसी को मजबूर कर दिया है और मैंने अभी भी 'lsof' द्वारा दिखाए गए जार फ़ाइलों के कई एफडी को देखा है। आप कोड मेरी समस्या हल! – waltersu

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