Java OOM 实战篇:应用故障之Java heap space 堆溢出实战原创
Java OOM优化专题大纲目录
第四篇:Java OOM 基础篇:常见的OutOfMemoryError 场景三: PermGen space 永久空间问题详解
第五篇:Java OOM 基础篇:常见的OutOfMemoryError 场景四: Permgen size 元空间问题详解
第六篇:Java OOM 实战篇:应用故障之Java heap space 堆溢出实战
第七篇:Java OOM 高级篇:体验了一把线上CPU100%及应用OOM的排查和解决过程
第八篇:Java OOM 高级篇:线上Docker 上Springboot程序OOM问题的排查分享
导语
堆溢出是应该是我们后端工程师日常经常遇到的问题,本篇用相对比较简单的过程写了一次堆溢出从测试发现到解决的过程,希望阅读本篇能对你有所帮助。
正文
以下是用于测试OOM的测试代码:
- public class HeapMemUseTest {
- public static void main(String[] args) {
- StringBuilder sb = new StringBuilder();
- while(true) {
- sb.append(System.currentTimeMillis());
- }
- }
- }
这段代码非常简单,其目的就是为了模拟OOM,将其编译后,通过以下命令运行:
- java -Xmx10m -Xms10m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=./oom.out HeapMemUseTest
其中的参数代表的意义为:
-Xmx和-Xms分别是用于指定该Java进程初使化的最小堆内存以及可以使用的最大堆内存的,这里设置为10M
-XX:+HeapDumpOnOutOfMemoryError
和-XX:HeapDumpPath
参数分别用于指定发生OOM是否要导出堆以及导出堆的文件路径
该命令一执行,立即就会发生OOM,并打印如下的日志:
- fenglibin -HP:~/eclipse_neon_workspace/Test/bin$ java -Xmx10m -Xms10m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=./oom.out HeapMemUseTest
- java.lang.OutOfMemoryError: Java heap space
- Dumping heap to ./oom.out ...
- Heap dump file created [5513523 bytes in 0.027 secs]
- Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
- at java.util.Arrays.copyOf(Arrays.java:3332)
- at java.lang.AbstractStringBuilder.ensureCapacityInternal(AbstractStringBuilder.java:124)
- at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:700)
- at java.lang.StringBuilder.append(StringBuilder.java:214)
- at HeapMemUseTest.main(HeapMemUseTest.java:13)
查看当前路径,oom.out文件已经生成了,该文件就是应用在发生OOM异常时自动导出的堆文件。那我们此时需要对该文件进行分析,因为其中记录了是什么对象导出了应用程OOM的发生。
分析OOM的工具推荐使用MAT,在配置好Java环境的电脑中,直接打开即可,不需要安装,然后通过MAT打开已经生成的OOM文件oom.out,出现如下提示,选择“Leak Suspects Report”执行内存泄漏检查分析:
点击Finish按钮后,MAT会将可疑的内存泄漏的对象都展现出来:
可以看到线程java.lang.Thread @ 0xff617e80 的main方法中,有一个本地变量占用了96.43%的堆内存,实际内存占用的是char[]数组,因而被检测出来为OOM可疑的元凶。点击红色框中的“See stacktrace”,可以直接看到该对象所在线程的堆栈信息:
直接定位到了发生OOM的代码所在位置,至此该示例分析完成,MAT工具本身还有其它许多的功能,这里就不一一细说了。