JVM调试排错--OOM
常见的内存溢出问题(内存和MetaSpace内存)
常见的内存溢出问题有,内存和metaspace内存
Java堆内存溢出
Java堆内存溢出有两种形式的错误:
- OutOfMemoryError: Java heap space
- OutOfMemoryError: GC overhead limit exceeded
OutOfMemoryError: Java heap space
在Java堆中不断地创建对象,并且GC-Roots到对象之间存在引用链,这样JVM就不会回收对象。
1 | public static void main(String[] args) { |
OutOfMemoryError: GC overhead limit exceeded
GC overhead limit exceed检查是Hotspot VM 1.6定义的一个策略,通过统计GC时间来预测是否要OOM了,提前抛出异常,防止OOM发生。Sun官方对此的定义是:“并行/并发回收器在GC回收时间过长时会抛出OutOfMemoryError。过长的定义是,超过98%的时间用来做GC并且回收了不到2%的堆内存。用来避免内存过小造成应用不能正常工作。”
1 | public void testOom1() { |
MetaSpace元数据内存溢出
JDK 8中将类信息移到了本地堆内存(Native Heap)中,将原有的永久代移动到了本地堆中成为MetaSpace,如果不指定该区域的大小,JVM将会动态地调整。
1 | public static void main(String[] args) { |
分析案例
线上OOM排查步骤:
使用dmesg命令查看系统日志
1
dmesg | grep -E 'kill|oom|out of memory'
可以查看操作系统启动后的系统日志,这里就是查看跟内存溢出相关联的系统日志。
启动项目,使用ps命令查看进程
1
2ps -aux | grep java
ps -ef | grep java查看你的Java进程的进程ID。
使用top命令
1
top
在结果列表中,会看到%MEM这一列,可以看到你的进程对内存的使用率特别高。
使用jstat命令
1
2jstat -gcutil 20886 1000 10
jstat -gcutil 8968 500 5用jstat工具对指定Java进程(20886是进程ID),按照指定间隔查看统计信息。
看到的东西类似下面那样:
1
2S0 S1 E O YGC FGC
26.80 0.00 10.50 89.90 86 954使用jmap命令查看
1
jmap -histo pid
打印出当前堆中所有每个类的实例数量和内存占用。
把当前堆内存的快照转储到dumpfile_jmap.hprof文件中,然后可以对内存快照进行分析。
1
jmap -dump:format=b,file=文件名 [pid]
例如:
1
jmap -dump:format=b,file=D:/log/jvm/dumpfile_jmap.hprof 20886
接着可以用MAT工具,或者是Eclipse MAT的内存分析插件,来对hprof文件进行分析。
All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.
Comment
WalineFacebook Comments