2013-04-30 7 views
7

मेरा अंतिम लक्ष्य कक्षाओं को फिर से लोड करने में सक्षम होना है जब वे पहले से ही JVM में लोड हो चुके हैं।एक क्लासलोडर को अनलोड करना

निम्नलिखित उत्तर पढ़ने के बाद Unloading classes in java?, मैं अपने स्वयं के क्लास-लोडर को लागू करने की कोशिश कर रहा हूं, जो स्वयं लोड होने वाले प्रत्येक वर्ग के लिए क्लास-लोडर (उसी प्रकार का स्वयं का) का एक अलग उदाहरण बनाता है।

तो, परिणाम प्रति वर्ग-लोडर प्रति वर्ग एक वर्ग है।

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

समस्या यह है कि - मैं अपनी कक्षा का उदाहरण अंतिम रूप() विधि का उपयोग करके कचरा एकत्रित कर सकता हूं, लेकिन मैं अपने क्लास-लोडर को उतारने के लिए नहीं मिला, या कचरा इकट्ठा नहीं कर सकता।
क्या कोई कोड उदाहरण है, एक साधारण परीक्षण है, जो दिखाता है कि यह कैसे किया जा सकता है?

धन्यवाद, किसी भी मदद की सराहना की जाएगी

संपादित:

स्पष्ट हो सकता है, मैं कोड उदाहरण में दिलचस्पी है, जहां नई वस्तुओं की इन्स्टेन्शियशन 'नई()' संकार्य के माध्यम से है , और क्लास लोडर मुख्य रूप से कक्षा में कक्षा को फिर से लोड नहीं कर रहा है, लेकिन अगले 'नए()' के बाद कहा जाता है।

+0

जब आप कस्टम 'क्लासलोडर' के माध्यम से कक्षा लोड करते हैं, तो आपको' क्लास 'ऑब्जेक्ट मिलेगा। इसके साथ 'नए' ऑपरेटर का उपयोग करना असंभव है। 'नया' का उपयोग करने का तात्पर्य है कि आप कोड को 'नए' द्वारा उपयोग की जाने वाली कक्षा से जोड़ा गया है और इसलिए, कक्षा को कचरा नहीं मिल सकता है जब आपका कोड 'नई' अभिव्यक्ति वाला अभी भी सक्रिय है। आपको इस बिंदु पर प्रतिबिंब का उपयोग करना होगा, उदा। 'कक्षा 'पर' newInstance() 'का आह्वान करें। बेशक, गतिशील रूप से लोड किया गया कोड स्वयं अपने दायरे में कक्षाओं को तुरंत चालू करने के लिए 'नया' का उपयोग कर सकता है। – Holger

उत्तर

9

कक्षा लोडर को कचरा इकट्ठा किया जाना चाहिए यदि उनके पास कोई संदर्भ नहीं है।

/* Copyright (c) 2011. Peter Lawrey 
* 
* "THE BEER-WARE LICENSE" (Revision 128) 
* As long as you retain this notice you can do whatever you want with this stuff. 
* If we meet some day, and you think this stuff is worth it, you can buy me a beer in return 
* There is no warranty. 
*/ 


import java.lang.reflect.Field; 
import java.net.URL; 
import java.net.URLClassLoader; 

public class LoadAndUnloadMain { 
    public static void main(String... args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException, InterruptedException { 
     URL url = LoadAndUnloadMain.class.getProtectionDomain().getCodeSource().getLocation(); 
     final String className = LoadAndUnloadMain.class.getPackage().getName() + ".UtilityClass"; 
     { 
      ClassLoader cl; 
      Class clazz; 

      for (int i = 0; i < 2; i++) { 
       cl = new CustomClassLoader(url); 
       clazz = cl.loadClass(className); 
       loadClass(clazz); 

       cl = new CustomClassLoader(url); 
       clazz = cl.loadClass(className); 
       loadClass(clazz); 
       triggerGC(); 
      } 
     } 
     triggerGC(); 
    } 

    private static void triggerGC() throws InterruptedException { 
     System.out.println("\n-- Starting GC"); 
     System.gc(); 
     Thread.sleep(100); 
     System.out.println("-- End of GC\n"); 
    } 

    private static void loadClass(Class clazz) throws NoSuchFieldException, IllegalAccessException { 
     final Field id = clazz.getDeclaredField("ID"); 
     id.setAccessible(true); 
     id.get(null); 
    } 

    private static class CustomClassLoader extends URLClassLoader { 
     public CustomClassLoader(URL url) { 
      super(new URL[]{url}, null); 
     } 

     @Override 
     protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { 
      try { 
       return super.loadClass(name, resolve); 
      } catch (ClassNotFoundException e) { 
       return Class.forName(name, resolve, LoadAndUnloadMain.class.getClassLoader()); 
      } 
     } 

     @Override 
     protected void finalize() throws Throwable { 
      super.finalize(); 
      System.out.println(this.toString() + " - CL Finalized."); 
     } 
    } 
} 

class UtilityClass { 
    static final String ID = Integer.toHexString(System.identityHashCode(UtilityClass.class)); 
    private static final Object FINAL = new Object() { 
     @Override 
     protected void finalize() throws Throwable { 
      super.finalize(); 
      System.out.println(ID + " Finalized."); 
     } 
    }; 

    static { 
     System.out.println(ID + " Initialising"); 
    } 
} 
: मैं @PeterLawrey (धन्यवाद) (यह तुम्हारा के रूप में एक ही बात करता है), कस्टम वर्ग लोडर finalize() विधि में एक लॉग डाल और देखा, वर्ग लोडर कचरा उनके भरी हुई कक्षा के बाद एकत्र कर रहे हैं से this code ले लिया जीसी है
+0

धन्यवाद, मुझे कोड उदाहरणों में अधिक दिलचस्पी थी जो 'नए()' ऑपरेंड के माध्यम से कक्षाओं के तत्काल दिखाते हैं, मेरे प्रश्न में स्पष्ट नहीं होने के लिए खेद है, मैं इसे संपादित कर दूंगा। –

1

में आईबीएम जे 9 वीएम चीजें अलग हैं क्योंकि क्लासलोडर अनलोडिंग केवल वैश्विक जीसी के दौरान होती है। यह वैश्विक जीसी में बड़ी रोकथाम के समय और मेमोरी से बाहर हो सकता है जब बड़ी संख्या में बनाए जा रहे क्लासलोडर्स हैं। मुझे जेएमएक्सएमपी के साथ इस समस्या का सामना करना पड़ा है, जहां com.sun.jmx.remote.opt.util.OrderClassLoaders क्लासलोडर का एक उदाहरण MBeanServerRequestMessage.CREATE_MBEAN_LOADER_PARAMS के प्रत्येक दूरस्थ संदेश के लिए बनाया गया है।

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