2011-11-05 25 views
9

मैं टॉमकैट एप्लिकेशन पर काम करता हूं जो जीसी ट्रिगर करने के लिए मेमोरी बार के साथ सीएमएस कलेक्टर का उपयोग करता है। जब मैं वेबपैप्स को फिर से लोड करता हूं तो मैं कभी-कभी ऐसी परिस्थिति में समाप्त होता हूं जहां पुरानी जीन जीसी को ट्रिगर करने के लिए पर्याप्त है लेकिन मृत क्लासलोडर्स एकत्र नहीं होते हैं।परम जीन कब एकत्र किया जाता है?

मैंने पढ़ा कि कक्षाओं को परम जीन में आवंटित किया गया है और अनुमान लगाया गया है कि उन्हें पुराने जन संग्रहों द्वारा अनदेखा किया जा रहा था। मैंने इस सिद्धांत का परीक्षण करने के लिए निम्नलिखित टेस्ट क्लास लिखा था।

package test; 

import java.io.IOException; 
import java.io.InputStream; 

import org.apache.commons.io.IOUtils; 

/* 
JVM Options: 
-server -XX:+UseMembar -XX:+UseConcMarkSweepGC 
-XX:+UseParNewGC -XX:CMSInitiatingOccupancyFraction=80 
-XX:+UseCMSInitiatingOccupancyOnly -Xms100m -Xmx100m 
-XX:PermSize=100m -XX:NewSize=10m -XX:MaxNewSize=10m 
-verbose:gc -Xloggc:gc.log -XX:+PrintGCTimeStamps 
-XX:+PrintGCDetails 
*/ 
public class ClassLoaderTest extends ClassLoader 
{ 
    @Override 
    protected synchronized Class<?> loadClass(String xiName, boolean xiResolve) 
     throws ClassNotFoundException 
    { 
    if (xiName.equals("test")) 
    { 
     // When asked to load "test", load Example.class 
     Class<?> c = Example.class; 
     String className = c.getName(); 
     String classAsPath = className.replace('.', '/') + ".class"; 
     InputStream stream = c.getClassLoader().getResourceAsStream(classAsPath); 
     byte[] classData = null; 
     try 
     { 
     classData = IOUtils.toByteArray(stream); 
     } 
     catch (IOException e) 
     { 
     e.printStackTrace(); 
     } 
     return defineClass(className, classData, 0, classData.length); 
    } 
    return super.loadClass(xiName, xiResolve); 
    } 

    public static class Example {} 
    public static ClassLoaderTest classLoaderTest; 

    public static void main(String[] args) throws Exception 
    { 
    // Allocate CL in new gen 
    classLoaderTest = new ClassLoaderTest(); 

    // Load a class - allocated in perm gen 
    classLoaderTest.loadClass("test"); 

    // Discard CL 
    classLoaderTest = null; 

    // Pause at end 
    Thread.sleep(99 * 60 * 1000); 
    } 

    public final byte[] mMem = new byte[85 * 1024 * 1024]; 
} 

मैं इस वर्ग के भाग गया और उत्पादन VisualVM का उपयोग कर नजर रखी और कहा कि वास्तव में कई पुराने और युवा पीढ़ी मृत classloader बिना हो रहा संग्रह एकत्र किया जा रहा थे और इसलिए बड़े बाइट सरणी स्मृति में बने रहे देखा।

VisualVM Visual GC

क्या पेर्म जनरल ट्रिगर करेगा एकत्र होने के लिए?

+0

आप जानते हैं कि "पर्म" क्या है [... सही?] (Http://en.wiktionary.org/wiki/permanent#Adjective) –

+4

जावा परम आवंटित स्मृति अभी भी एकत्र की जा सकती है। JVM पर्म जनरल का उपयोग डेटा रखने के लिए करता है जिसे वह बहुत ही कम से कम मुक्त होने की अपेक्षा करता है। – mchr

उत्तर

4

जेवीएम विकल्प "CMSPermGenSweepingEnabled" और "CMSClassUnloadingEnabled" देखें। (उनके उपयोग के नेट पर बहुत सी चर्चाएं हैं।) विशेष रूप से, पहले व्यक्ति को कचरा संग्रह चलाने में पर्मजेन को शामिल करने का अनुमान है। डिफ़ॉल्ट रूप से, पर्मजेन स्पेस कचरा संग्रह में कभी शामिल नहीं होता है (और इस प्रकार सीमा के बिना बढ़ता है)।

+1

यह बिना सीमा के बढ़ता है, एक बहुत ही निश्चित ऊपरी सीमा है। यही कारण है कि आप अक्सर डरावनी क्लासलोडर रिसाव प्राप्त करते हैं: https://blogs.oracle.com/fkieviet/entry/classloader_leaks_the_dreaded_java –

+0

@ कैमरॉन स्किनर + प्वाइंट लिया गया! यह MaxPermSize के संबंध में बढ़ने के लिए _attempts_ :-) – mazaneicha

+1

मैंने -XX: + CMSPermGenSweepingEnabled -XX जोड़ने का प्रयास किया: + CMSClassUnloading मेरे जेवीएम तर्कों में सक्षम है। मैंने पाया कि केवल -XX: + CMSClassUnloadingEnabled वास्तव में कुछ भी किया था। मुझे यह भी आश्चर्य हुआ कि परम जीन केवल दूसरे युवा जन संग्रह के बाद 2 मिनट के बाद ही एकत्र किया गया था। – mchr

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