程序员知识图谱-Java 内存溢出的排查方法

内存溢出分类

Java 里面内存溢出主要分以下几种:

堆溢出

1、内存溢出(无法申请到内存) jstat 查看内存使用情况,检查堆参数,一般是申请的内存太大,比如一个特别大的 byte 数组

2、内存泄漏(对象无法回收) 可以使用 MAT 工具里面的 Path to GC Roots 定位,一般是一个特大不能回收的对象

栈溢出

  1. StackOverflowError 方法调用层次太深,内存不够新建栈帧,比如一个没有结束条件的递归
  2. OutOfMemoryError 线程太多,内存不够新建线程

MetaSpace 数据区溢出

动态生成大量 Class

本地直接内存溢出

申请一个大的直接内存

数据超限内存溢出

分配的数据结构在此平台不可寻址

排查方法

JDK 自带命令

jstat -gcutil 33816 250 20 # 监控 jvm 的内存使用情况
jps -ml # 输出虚拟机启动时传递给主类 main() 的参数,输出主类的全名
jmap -F -dump:live,format=b,file=dump.bin 85962 # dump 堆内存
# 分析方法
# 可以使用 VisualVM,主要查看是否存在大对象,然后分析为什么没有被回收
jstack -F -l -m 85962 # 显示虚拟机快照
jstack -l PID >> test.txt
jmap -histo pid # 实时查看JVM对象大小的排序结果,但无法看到对象的具体内容

Arthas

# 找到最耗CPU的方法
thread -n 5
# 观察方法的返回
watch com.test.MyClass query returnObj
# 反编译类
jad com.test.MyClass
# 监控调用情况
monitor -c 5 com.test.MyClass query
# 查看分段的调用时间
trace com.test.MyClass query
# 查看方法完整的调用链
stack com.test.MyClass query
# 记录调用现场
tt -t com.test.MyClass query

参数检查

-Xms 初始堆大小
-Xmx 最大堆大小
-Xmn 新生代大小
XX:MaxMetaSpaceSize 元数据区大小
Survivor Eden与Survivor区的大小比值

本文亦通过 NoOne 的个人博客 发表。

猜你喜欢

转载自blog.csdn.net/hunterzhang86/article/details/127308410