(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
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問題