- 设置idea java启动参数
设置 堆内存200M 新生代50M 并打印GC日志
-XX:+PrintGCDetails -Xmx200M -Xms200M -Xmn50M -XX:+PrintTenuringDistribution -XX:+PrintGCDateStamps
- 单独运行main方法查看程序本身所占用的内存
默认Eden区使用3898k 10%
- 测试GC过程
public class test {
public static void main(String[] args) {
//main方法默认使用 3898K 10%
System.out.println("第一轮GC");
createObj30M();//使用方法创建 待方法结束后对象成为待清除的垃圾
byte[] arr1=new byte[1024*1024*2];
byte[] arr2=new byte[1024*1024*2];
//Eden区100% 第一次触发gc arr1 arr2移动到 from
createObj2M();
System.out.println("第二轮GC");
//第二次想触发gc arr1 arr2已经移动到 from 使eden100%
createObj30M();
byte[] arr3=new byte[1024*1024*2];
byte[] arr4=new byte[1024*1024*2];
//第二次触发 gc arr1 arr2 因为form区内存不够 被移动至老年代 new threshold 7未达到年龄"premature promotion"(过早提升)
createObj2M();
}
public static void createObj30M(){
byte[] arr=new byte[1024*1024*30];
}
public static void createObj2M(){
byte[] arr=new byte[1024*1024*2];
}
}
日志情况:
- GC日志参数解析:
5.注意到第二次 Minor GC 的情况, 。 可以看出明显的新生代的 Survivor 空间不足。正因为 Survivor 空间不足, 那么从 Eden 存活下来的和原来在 Survivor 空间中不够老的对象占满 Survivor 后, 就会提升到老年代, 可以看出, 这属于一个典型的 JVM 内存问题, 称为 “premature promotion”(过早提升)。
"premature promotion” 在短期看来不会有问题, 但是经常性的 "premature promotion”, 最总会导致大量短期对象被提升到老年代, 最终导致老年代空间不足, 引发另一个 JVM 内存问题 “promotion failure”(提升失败: 即老年代空间不足以容乃 Minor GC 中提升上来的对象)。 “promotion failure” 发生就会让 JVM 进行一次full垃圾收集进而腾出空间接受新生代提升上来的对象, 垃圾收集时间比 Minor GC 长, 导致吞吐量下降、 时延上升, 将对用户体验造成影响。
6. minor GC 和FullGC
当前老年代最大可用连续空间大于平均历次晋升到老年代大小,如果大于,则进行MinorGC,否则进行FullGC
7.触发FullGc 情况:
(1)System.gc()方法的调用。此方法的调用是建议JVM进行Full GC,虽然只是建议而非一定,但很多情况下它会触发 Full GC,从而增加Full GC的频率,也即增加了间歇性停顿的次数。强烈影响系建议能不使用此方法就别使用,让虚拟机自己去管理它的内存,可通过通过-XX:+ DisableExplicitGC来禁止RMI(Java远程方法调用)调用System.gc。
(2)旧生代空间不足。旧生代空间只有在新生代对象转入及创建为大对象、大数组时才会出现不足的现象,当执行Full GC后空间仍然不足,则抛出错误:java.lang.OutOfMemoryError: Java heap space 。为避免以上两种状况引起的FullGC,调优时应尽量做到让对象在Minor GC阶段被回收、让对象在新生代多存活一段时间及不要创建过大的对象及数组。
(3)Permanet Generation空间满了。Permanet Generation中存放的为一些class的信息等,当系统中要加载的类、反射的类和调用的方法较多时,Permanet Generation可能会被占满,在未配置为采用CMS GC的情况下会执行Full GC。如果经过Full GC仍然回收不了,那么JVM会抛出错误信息:java.lang.OutOfMemoryError: PermGen space 。为避免Perm Gen占满造成Full GC现象,可采用的方法为增大Perm Gen空间或转为使用CMS GC。
(4)通过Minor GC后进入老年代的平均大小大于老年代的可用内存。如果发现统计数据说之前Minor GC的平均晋升大小比目前old gen剩余的空间大,则不会触发Minor GC而是转为触发full GC。
(5)由Eden区、From Space区向To Space区复制时,对象大小大于To Space可用内存,则把该对象转存到老年代,且老年代的可用内存小于该对象大小
8.fullgc 原因跟踪
S0C:第一个幸存区的大小
S1C:第二个幸存区的大小
S0U:第一个幸存区的使用大小
S1U:第二个幸存区的使用大小
EC:伊甸园区的大小
EU:伊甸园区的使用大小
OC:老年代大小
OU:老年代使用大小
MC:方法区大小
MU:方法区使用大小
CCSC:压缩类空间大小
CCSU:压缩类空间使用大小
YGC:年轻代垃圾回收次数
YGCT:年轻代垃圾回收消耗时间
FGC:老年代垃圾回收次数
FGCT:老年代垃圾回收消耗时间
GCT:垃圾回收消耗总时间
(单位:字节)
9.使用dump文件分析
Dump文件是进程的内存镜像。可以把程序的执行状态通过调试器保存到dump文件中,可以理解为程序的运行日志。
jmap -dump:live,format=b,file=dump.out 23296
dump文件分析工具
jdk自带Jconsole,Visualvm