演示JVM中对象分配内存过程和OOM发生原因
工具:jvisualvm
测试代码:
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区迅速上涨,当满了会放到幸存区,如果幸存区较小会直接放到老年区
线上查看gc详情
启动命令添加jvm参数: -XX:+PrintGCDateStamps -XX:+PrintGCDetails -verbose:gc -Xloggc:gc.log