网站要实名认证吗,html5网站建设平台,wordpress frontpage,wordpress touchy作者简介#xff1a;大家好#xff0c;我是smart哥#xff0c;前中兴通讯、美团架构师#xff0c;现某互联网公司CTO 联系qq#xff1a;184480602#xff0c;加我进群#xff0c;大家一起学习#xff0c;一起进步#xff0c;一起对抗互联网寒冬 学习必须往深处挖… 作者简介大家好我是smart哥前中兴通讯、美团架构师现某互联网公司CTO 联系qq184480602加我进群大家一起学习一起进步一起对抗互联网寒冬 学习必须往深处挖挖的越深基础越扎实
阶段1、深入多线程阶段2、深入多线程设计模式阶段3、深入juc源码解析阶段4、深入jdk其余源码解析阶段5、深入jvm源码解析
一、简介
本章我们将通过示例代码演示Java堆内存区域是如何发生内存溢出的并根据内存快照进行分析。
我们回顾下堆内存溢出的一个场景系统负载很高不停的在Eden区创建新对象直到触发Young GC但是由于并发太高Young GC发现Eden区存活对象非常多Survivor无法容纳只能把大批存活对象转移到老年代。经过几次这种Young GC之后老年代也满了于是触发Full GC但是Full GC之后老年代里还是塞满了对象导致Young GC过后的存活对象无处可安放最终引发堆内存溢出。 二、示例程序 2.1 程序源码 package com.mx.jvm;import java.util.ArrayList;import java.util.List;public class Demo3 {public static void main(String[] args) {long counter 0L;ListObject list new ArrayListObject();while (true) {list.add(new Object());System.out.println(当前创建了第 counter 个对象);}}上述代码很简单就是不停的创建对象由于对象由一个while循环外部的List引用着且main()方法是无限执行的所以这些创建的对象始终不会被回收掉。这样最终Eden区、老年代的空间都会被占满。 2.2 JVM参数
我们设置下堆内存的总大小为5MB-Xms5m -Xmx5m -XX:UseParNewGC -XX:UseConcMarkSweepGC -XX:PrintGCDetails -Xloggc:gc.log -XX:HeapDumpOnOutOfMemoryError -XX:HeapDumpPath./这样就可以快速触发堆内存溢出。程序执行后的打印日志输出如下 当前创建了第160063个对象当前创建了第160064个对象当前创建了第160065个对象java.lang.OutOfMemoryError: Java heap spaceDumping heap to ./\java_pid6412.hprof ...Heap dump file created [7250823 bytes in 0.058 secs]Exception in thread main java.lang.OutOfMemoryError: Java heap spaceat java.util.Arrays.copyOf(Arrays.java:3210)at java.util.Arrays.copyOf(Arrays.java:3181)at java.util.ArrayList.grow(ArrayList.java:261)at java.util.ArrayList.ensureExplicitCapacity(ArrayList.java:235)at java.util.ArrayList.ensureCapacityInternal(ArrayList.java:227)at java.util.ArrayList.add(ArrayList.java:458)at com.mx.jvm.Demo3.main(Demo3.java:12)可以看到在5MB的堆内存中不断创建Obejct对象当创建到第160065个对象时堆内存实在放不下了从而引发java.lang.OutOfMemoryError。 三、问题分析
我们通过程序日志中的报错“java.lang.OutOfMemoryError: Java heap space”知道发生了Java堆内存溢出。针对Java堆内存溢出一般不用看GC日志因为堆内存溢出伴随的GC日志内容会非常多我们直接分析dump出的内存快照即可。
采用MAT打开内存快照java_pid6412.hprof进程名不同文件名也略有区别 可以看到一大堆对象占据了81.19%的堆内存我们直接点击See stacktrace看看这些对象是在程序哪里创建出来的 很显然main方法的第12行一直调用list.add(new Object())由此直接引发了内存溢出我们只要有针对性的修复我们代码的bug即可。 四、总结
本章我们通过代码示例模拟了堆内存溢出的场景Java堆内存也是最容易出现内存溢出的区域。基本的分析思路就是dump出事发现场的内存快照然后通过MAT进行查看分析出内存占用最多的对象然后分析线程调用栈找到代码位置最后进行优化即可。
从下一章开始我们将给出真实的生产环境案例看看这些案例是如何引起OOM以及排查和解决的思路方法。