从头开始学JVM--------理解GC日志

一、需要掌握的虚拟机参数

堆内存命令
       -Xms  设置堆最小内存,默认机器内存的 1/64
       -Xmx  设置堆最大内存,默认机器内存的 1/4
栈内存命令
       -Xss   设置每个线程的栈内存
 GC
       -XX:+HeapDumpOnOutOfMemoryError   分析堆内存溢出原因
       -XX:+HeapDumpPath=/user/local/           将堆内存溢出原因记录到指定的文件
       -XX:+PrintGCDetails                                   打印GC回收细节     
 指明垃圾回收器
       -XX:+UseG1GC     使用G1垃圾回收器

二、模拟内存溢出

import java.util.ArrayList;
import java.util.List;

public class TestBean {

    static class OOMObject {

        private byte[] data = new byte[512 * 1024];
    }

    /**
     * VM Args : -Xms5m -Xmx5m  -XX:+PrintGCDetails
     */
    public static void main(String[] args) {
        int count = 0;
        List<OOMObject> list = new ArrayList<>();

        while (true) {
            list.add(new OOMObject());
        }
    }
}

        程序运行结果:

三、分析结果

        从结果来看,总共发生了4次垃圾回收。

        (1)第一次垃圾回收结果日志,仅发生在年轻代中。我手动换行一下,看的更加清楚。

[GC (Allocation Failure)

[PSYoungGen: 1024K->488K(1536K)] 1024K->640K(5632K), 0.0020076 secs]

[Times: user=0.00 sys=0.00, real=0.00 secs] 

        GC(Allocation Failure):引起垃圾回收的原因。本次 GC 是因为年轻代中没有足够的空间存放新创建的对象。

        PSYoungGen: 1024K->488K(1536K)   :年轻代中垃圾回收之前使用了1024K的内存空间,垃圾回收后使用了488K内存空间。1536K表示年轻代的总的内存空间。

        1024K->640K(5632K):当前堆内存在垃圾会收前使用了1024K,垃圾回收后使用了640K,总的堆内存大小为5632K。

        0.0020076 secs:GC回收时间。单位是秒。本次是2ms。

        Times: user=0.00 sys=0.00, real=0.00 secs::GC事件的持续时间

        (2)第三次垃圾回收结果日志。发生在 年轻代,老年代,元空间中。

[Full GC (Ergonomics)

[PSYoungGen: 1524K->487K(1536K)]

[ParOldGen: 4087K->4011K(4096K)] 5611K->4498K(5632K),

[Metaspace: 3206K->3206K(1056768K)], 0.0116127 secs] [Times: user=0.03 sys=0.00, real=0.01 secs] 

        Full GC (Ergonomics) :我个人理解是全面的垃圾回收,在整个堆内存中进行回收,而不是仅仅在某个分代中。

        PSYoungGen: 1524K->487K(1536K):年轻代垃圾回收前使用了1524K,回收后使用487K,年轻代内存大小共1536K。

        ParOldGen: 4087K->4011K(4096K):老年代垃圾回收钱使用了4087K,垃圾回收后使用了4011K,老年代内存总大小为4096K。

        5611K->4498K(5632K):堆内存回收前使用了5611K,回收后使用了4498K,堆内存总大小为5632K。

        Metaspace: 3206K->3206K(1056768K):元空间垃回收前后都是3206K,说明没有发生垃圾回收。

        0.0116127 secs :本次垃圾回收共11ms。

       Times: user=0.03 sys=0.00, real=0.01 secs:本次垃圾回收实际花费时间是 0.01秒。

      (3)第四次垃圾回收结果日志。发生在 年轻代,老年代,元空间中。

[Full GC (Ergonomics)

[PSYoungGen: 999K->999K(1536K)]

[ParOldGen: 4011K->4010K(4096K)] 5011K->5010K(5632K),

[Metaspace: 3206K->3206K(1056768K)], 0.0097889 secs]

[Times: user=0.00 sys=0.00, real=0.01 secs] 

        年轻代已经回收不动,老年代仅仅回收了1K。 堆内存从5011K实际减小到5010K,仅仅减少1K。而堆内存最大限制为5632K,因此可以预见到,即将出现内存溢出。果不其然,从程序实际执行结果来看,出现了 OOM。

        通过GC日志,可以看出,当前应用程序的内存使用情况十分糟糕,老年代几乎被占满。

        所以说,GC日志对监控JVM是否正常运行,有着十分重要的作用。

        一旦上线的项目出现了OOM,GC可以快速定位到哪个内存区域出现,真乃救命稻草啊。

四、其它注意点

        GC时间的时间不能过长,否则就会影响系统的吞吐量。

        老年代内存使用率接近100%,并且回收后仍然是这样,得注意。要么是堆内存太小,要么是系统中出现了内存泄露。

posted @ 2022-07-17 12:14  小大宇  阅读(70)  评论(0编辑  收藏  举报