演示JVM中对象分配内存过程和OOM发生原因

发布时间 2024-01-10 10:55:07作者: spiderMan1-1

工具:jvisualvm

image

测试代码:

    public static void main(String[] args) throws Exception{
        List<byte[]> list = Lists.newArrayList();
        System.in.read();
        while (true){
            System.out.println("-----"+ DateUtil.now());
            final int mem =1024*1024*4;
            byte[] bytes = new byte[mem];
            list.add(bytes);
            //阻塞通过手动按键控制
            System.in.read();
        }
    }

流程:

  • 在jvm中,如果new一个对象,会放在年轻代中的Eden区。等Eden快满了会后发生 Minor GC,如果对象不能及时清理,会放到下面的survior幸存区,并将对象年龄标记为1。等下一次GC,如果上传的对象还没有及时回收,年龄会上涨为2,经过15次回收,还是不能回收会放到old老年代。老年代满了会发生oom
  • 幸存区分为s0和s1。两个可以是from也可以是to,使用的是复制清除算法,所以他们中间只有一个会存放对象,另一个永远为空。例如:s1是from区,s0为to区,当s1的对象满了之后,会复制到s0区,让s0变成from区,s1变成to区,来回交替15放到老年代
  • 上面的代码会每次放4M数据,会发现Eden区迅速上涨,当满了会放到幸存区,如果幸存区较小会直接放到老年区
    image
    image

线上查看gc详情

启动命令添加jvm参数: -XX:+PrintGCDateStamps -XX:+PrintGCDetails -verbose:gc -Xloggc:gc.log