阅读导航
<b><font color="#0076b3">类加载机制</font></b> 👉
<b><font color="#0076b3">运行时数据区</font></b> 👉
<b><font color="#0076b3">GC垃圾回收</font></b> 👉
<b><font color="#f15a23">OOM内存溢出</font></b>
<b><font color="#0076b3">JVM性能调优</font></b> 👉
<b><font color="#0076b3">JVM常用工具</font></b> 👉
<b><font color="#0076b3">JIT即时编译 </font></b>👉
内存
内存溢出
<b> 栈内存溢出<br>StackOverflowError</b>
<b>原因:线程请求栈的深度超过当前Java虚拟机栈的最大深度(默认大小是1M,1024KB)</b>
代码举例
解决:检测是否有无穷递归、死循环,如果不是bug,可以通过调整虚拟机栈的大小来解决(-Xss2m)
<b> 堆内存溢出<br>OutOfMemory</b>
<b>原因:堆内存被用光,或者内存泄漏堆积导致</b>
OOM
<b>对象太多</b>(Java heap space)
修复内存泄露,或使用 -Xmx 增加堆内存大小
代码举例
<b>GC回收超时</b>(GC overhead limit exceeded)
使用 -XX:-UseGCOverheadLimit 取消 GC 开销限制
<b>本地内存不足</b>(Direct buffer memory)
打印的堆栈跟踪信息,使用操作系统本地工具进行诊断
<b>线程太多</b>(unable to create new native thread)
减少虚拟机栈的大小或增大虚拟机占用比例
<b>元空间内存不足</b>(Metaspace)
使用-XX: MaxMetaSpaceSize 增加 metaspace 大小
内存泄漏
<b>程序在申请内存后,无法释放已申请的内存空间</b>
导致频繁 GC
<b>jstat -gc</b> pid 1000
每秒打印一次GC详细信息(C:容量|U:已使用)(E:Eden|O:Old|M:MetaSpace)
S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT GCT
<b>jstat -gcutil</b> 1000 3
查看最近3次GC空间占比
S0 S1 E O M CCS YGC YGCT FGC FGCT GCT
使用 jmap 生成 堆转储 快照文件 jmap -histo:live pid
通过 MAT 查看 Histogram 图即可找出是哪块代码
查看线程信息
<b>top -Hp</b> pid
左上角显示Threads: 28 total,下面显示详细的线程信息
线程数
pstree -p 8379 | wc -l
ls /proc/8379/task | wc -l
ps hH p 8379 | wc -l
CPU
CPU 占用过高
先用 <b>top </b>显示进程列表,找到占用率最高的 PID<br>
此时也可挂上阿里的Arthas查看占用高的线程
再使用 <b>top -Hp</b> pid 找到占用最高的线程 tid
如果是业务线程,检查死循环或者大量计算的代码
如果是收集线程,检查是否频繁 FGC
如果 FGC 的回收正常,说明此时只是压力大
如果 FGC 每次回收很少,说明有内存泄漏
<b>printf '%x\n'</b> tid 将线程ID转换为16进制 (小写)
最后使用<b> jstack</b> pid | <b>grep</b> tid -A60
频繁上下文切换
<b>vmstat</b> 2 3
每隔2秒打印一次CPU信息,共打印3次
cs:表示上下文切换次数(context switch)
<b>pidstat -w</b> pid
针对 pid 进行上下文切换监控
cswch/s:每秒自愿上下文切换(进程无法获取到可供执行的资源从而自愿发生上下文切换)
nvcswch/s:每秒非自愿上下文切换(进程时间片用完、被高优先级进程抢走、系统中断等发生的非自愿的场景)
关于作者
<b style=""><font color="#b296c7">我的博客</font></b> 👉
<b><font color="#00a650">微信公众号</font></b> 👉
<b><font color="#f15a23">GitHub 主页</font></b> 👉