上一周我有幸观看了高级架构师李国讲师的直播,内容是关于 Java 内存问题排查和解决。
下面是我做的笔记,在这里分享一下。
直播背景
李国,曾任京东、陌陌高级架构师。负责过京东金融调用链系统 SGM,以及数据库中间件 CDS 的开发工作。曾负责陌陌基础社交业务线的整体架构工作,对高并发下的 JVM 调优有丰富的经验。
/proc/meminfo
# cat /proc/meminfo MemTotal: 3881692 kB MemFree: 249248 kB MemAvailable: 1510048 kB Buffers: 92384 kB Cached: 1340716 kB 40+ more ...Metaspace
默认无上限-Xmx -Xms
控制大小JVM 进程内存 = 堆内内存 + 堆外内存
堆外内存 = 元空间 + CodeCache + 本地内存
可分配内存大小 = 物理内存 + SWAP
-Xmx -Xms
-XX:MaxMetaspaceSize -XX:MetaspaceSize
-Xss
-XX:MaxDirectMemorySize
jmap
pmap
OutOfMemoryError
,简称OOMMemory Leak
,简称MLCMS
将在 Java 14 正式移除G1
主流应用的垃圾回收器ZGC
大容量(16TB),低延迟(10ms)的垃圾回收器MaxGCPauseMillis
预定目标,自动调整G1HeapRegionSize
小堆区大小InitiatingHeapOccupancyPercent
堆内存比例阈值,启动并发标记-XX:MaxTenuringThreshold
在 CMS 下默认为 6,G1 下默认为 15ss -antp > $DUMP_DIR/ss.dump 2>&1
netstat -s > $DUMP_DIR/netstat-s.dump 2>&1
sar -n DEV 1 2 > $DUMP_DIR/sar-traffic.dump 2>&1
iostat -x > $DUMP_DIR/iostat.dump 2>&1
free -h > $DUMP_DIR/free.dump 2>&1
java -Xmx20m -Xmn4m -XX:+HeapDumpOnOutOfMemoryError - OOMTest
[18.386s][info][gc] GC(10) Concurrent Mark 5.435ms
[18.395s][info][gc] GC(12) Pause Full (Allocation Failure) 18M->18M(19M)
10.572ms
[18.400s][info][gc] GC(13) Pause Full (Allocation Failure) 18M->18M(19M)
5.348ms
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space at OldOOM.main(OldOOM.java:20)
java -Xmx20m -Xmn4m -XX:+HeapDumpOnOutOfMemoryError -XX:MetaspaceSize=16M -XX:MaxMetaspaceSize=16M MetaspaceOOMTest
6.556s][info][gc] GC(30) Concurrent Cycle 46.668ms
java.lang.OutOfMemoryError: Metaspace
Dumping heap to /tmp/logs/java_pid36723.hprof ..
java -XX:MaxDirectMemorySize=10M -Xmx10M OffHeapOOMTest
Exception in thread "Thread-2" java.lang.OutOfMemoryError: Direct buffer memory
at java.nio.Bits.reserveMemory(Bits.java:694)
at java.nio.DirectByteBuffer.<init>(DirectByteBuffer.java:123)
at java.nio.ByteBuffer.allocateDirect(ByteBuffer.java:311)
at OffHeapOOMTest.oom(OffHeapOOMTest.java:27)...
java -Xss128K StackOverflowTest
Exception in thread "main" java.lang.StackOverflowError
at
java.io.PrintStream.write(PrintStream.java:526)
at
java.io.PrintStream.print(PrintStream.java:597)
at
java.io.PrintStream.println(PrintStream.java:736)
at
StackOverflowTest.a(StackOverflowTest.java:5)
hashCode
和 equals
方法,造成了放入 HashMap
的所有对象,都无法被取出来equals
和 hashCode
方法fullname
和 other
为空的时候CentOS7,JDK1.8,SpringBoot
heapdump
文件wrk
进行压测,发现 20 个用户并发,内存溢出wrk -t20 -c20 -d300s http://127.0.0.1:8084/api/test
-t 使用的线程数
-c 开启的连接数量
-d 持续压测的时间
jmap -dump:format=b,file=heap.bin 37340
jhsdb jmap --binaryheap --pid 37340
CentOS7,JDK1.8,JBoss
Websocket
心跳检测失效,造成链接不释放,无效包持续发送XX:+HeapDumpOnOutOfMemoryError
不起作用dmesg oom-killer
System.exit()
java com.cn.AA &
kill -9
dmesg
命令中发现确实被 oom-kill
kill -9 && kill -15
oom-kill
free
区一直减少,并无其他进程抢占资源top
命令,发现 RES
占用严重超出了 -Xmx
的设定unsafe
类操作了堆外内存pmap
查看内存分布gdb
导出内存块perf
监控函数调用gperftools
分析内存分配函数一、问题发现(最困难)
free
jmap
GClog
和其他日志jstack
对线程进行摸底二、采取措施
三 、重复观察
四、问题解决