對象什麼時候進入老年代、什麼時候發生full gc

 

1、對象什麼時候進入老年代

(1)當對象首次建立時, 會放在新生代的eden區, 若沒有GC的介入,會一直在eden區, GC後,是可能進入survivor區或者年老代java

(2)當對象年齡達到必定的大小 ,就會離開年輕代, 進入老年代。 而對象的年齡是由GC的次數決定的數組

-XX:MaxTenuringThreshold=n  新生代的對象最多經歷n次GC, 就能晉升到老年代, 但不是必要條件   app

-XX:TargetSurvivorRatio=n  用於設置Survivor區的目標使用率,即當survivor區GC後使用率超過這個值, 就可能會使用較小的年齡做爲晉升年齡ui

(3)除年齡外, 對象體積也會影響對象的晉升的, 若對象體積太大, 新生代沒法容納這個對象this

-XX:PretenureSizeThreshold  即對象的大小大於此值, 就會繞過新生代, 直接在老年代分配, 此參數只對串行回收器以及ParNew回收有效, 而對ParallelGC回收器無效spa

 

2、什麼時候發生full gc

public class ConcurrentMarkSweep {

    private static final int SIZE= 1024 * 1024;

    public static void main(String[] args) throws Exception{
        byte[] a1, a2, a3, a4;
        a1 = new byte[2 * SIZE];
        a2 = new byte[2 * SIZE];
        a3 = new byte[2 * SIZE];
        a4 = new byte[2 * SIZE];
        System.in.read();
    }
}

 

1. System.gc()方法的調用 
system.gc(), 此方法的調用是建議JVM進行Full GC, 可經過經過-XX:+ DisableExplicitGC來禁止RMI調用System.gc。 code


2. old/Tenured 空間不足 server

老年代空間在新生代對象轉入及建立爲大對象、大數組時對象

當執行Full GC後空間仍然不足,報錯:java.lang.OutOfMemoryError: Java heap space blog

java -Xmx10m -Xms10m -Xmn10m -XX:+UseParNewGC  -XX:+UseConcMarkSweepGC -XX:+UseCMSInitiatingOccupancyOnly  -XX:CMSInitiatingOccupancyFraction=75 -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintHeapAtGC gc.ConcurrentMarkSweep

 

3. perm/metaspace 空間不足

JVM規範中運行時數據區域中的方法區,在HotSpot虛擬機中又被習慣稱爲永生代或者永生區,

Permanet Generation中存放的爲一些class的信息、常量、靜態變量等數據,當系統中要加載的類、反射的類和調用的方法較多時,

當Full GC後空間仍然不足,報錯:java.lang.OutOfMemoryError: PermGen space

java -cp .:/Users/gl/IntelliJProjects/JBase/jdk/build/tmp/lib/javassist-3.20.0-GA.jar  -XX:MaxMetaspaceSize=32M gc.Metaspace

在個人MAC上,大約生成21165個class: Exception in thread "main" javassist.CannotCompileException: by java.lang.OutOfMemoryError: Metaspace
public class Metaspace {

   static  ClassPool cp = ClassPool.getDefault();

    public static void main(String[] args) throws Exception{
        for (int i = 0; ; i++) {
            System.out.println(i);
            CtClass ctClass = cp.makeClass("com.mp.Person" + i );
            //添加屬性
            ctClass.addField(CtField.make("private int age;", ctClass));
            //添加setAge方法
            ctClass.addMethod(CtMethod.make("public void setAge(int age){this.age = age;}", ctClass));
            ctClass.addMethod(CtMethod.make("public int getAge(){return this.age;}", ctClass));
            //If the program is running on some application server, the context class loader might be inappropriate to load the class.
            //若是沒有調用,則沒影響
            ctClass.toClass();
        }
    }
}

 

 

4. CMS GC時出現promotion failed和concurrent mode failure 

promotion failed是在進行Minor GC時,survivor space放不下, 對象只能放入老年代,而此時老年代也放不下形成的;

concurrent mode failure是在執行CMS GC的過程當中同時有對象要放入老年代,而此時老年代空間不足形成的

java -Xmx10m -Xms10m -Xmn10m -XX:+UseParNewGC  -XX:+UseConcMarkSweepGC -XX:+UseCMSInitiatingOccupancyOnly  -XX:CMSInitiatingOccupancyFraction=75 -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintHeapAtGC gc.ConcurrentMarkSweep

 

 

 

5. 判斷當前新生代的對象是否可以所有順利的晉升到老年代,若是不能,就提前觸發一次老年代的收集

java -Xmx14m -Xms14m -Xmn10m -XX:+UseParNewGC  -XX:+UseConcMarkSweepGC -XX:+UseCMSInitiatingOccupancyOnly  -XX:CMSInitiatingOccupancyFraction=75 -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintHeapAtGC ConcurrentMarkSweep

# JVM 經過 CMSInitiatingOccupancyFraction 的值肯定是否gc
-XX:+UseCMSInitiatingOccupancyOnly
-XX:CMSInitiatingOccupancyFraction=75

以下,Meta space 使用爲達到75%, 卻一直在發生FGC

若是永久代設置的很小,則會發生系統剛啓動就執行CMS

 

參考:

佔小狼:一個有意思的CMS問題

相關文章
相關標籤/搜索