JVM OOM
- 堆区
Heap - 方法区
Per - 栈区
StackOverFlow
元空间
调优参数
1 | -XX:MetaspaceSize=10m |
1、最大、最小设置成一样大。
2、程序运行起来后,通过visualVM、arthas查看占用了多少内存,向上调优,预留20%以上的空间。
虚拟机堆
1 | [GC (Allocation Failure) [PSYoungGen: 1344K->320K(2048K)] 7894K->7118K(9216K), 0.0071516 secs] [Times: user=0.01 sys=0.00, real=0.00 secs] |
- 调优参数
-Xms10m -Xmx10m
1、预留30%以上的空间
2、周期性看日志,重点关注full gc频率
虚拟机栈
- 调优参数
-Xmss200k
栈大小相同,栈深度不同,为什么?
因为栈上会分配数据。导致栈帧变大。深度会变浅。
调优工具
- jps
-q:只显示Java进程的ID
-m:输出Java进程的ID + main函数所在类的名词 + 传递给main函数的参数
-l:输出Java进程的ID + main函数所在类的全限定名(包名 + 类名)
-v:输出Java进程的ID + main函数所在类的名称 + 传递给JVM的参数
应用:可通过此方式快速查看JVM参数是否设置成功
-V、hostid基本用不到,这里就不做介绍了,感兴趣的同学可以自行百度学习。
- 如何识别Java进程
jps输出的信息全是Java进程的信息,是如何做到的?
Java进程在创建的时候,会生成相应的文件,进程相关的信息会写入该文件中。Windows下默认理解是
- jstate
Hotspot自带的工具,通过该工具可实时了解某个进程的class、compile、gc、memory的相关信息。具体可通过该工具查看哪些信息可通过jstat -options查看.
为什么说是实时呢,因为底层实现是mmap,及内存映射文件
jstat输出的这些值从哪来的
PerfData文件
Windows下默认理解是C:\Users\username\AppData\Local\Temp\hsperfdata_username
Linux下默认路径是/tmp/hsperfdata_usernamePerfData文件
1、文件创建
取决于两个参数
-XX:-/+UsePerfData
默认是开启的
关闭方式:-XX:-UsePerfData。如果关闭了,就不会创建PerfData文件
-XX:-/+PerfDisableSharedMem(禁用共享内存)
默认是关闭的,即支持内存共享。如果禁用了,依赖于PerfData文件的工具就无法正常工作了
2、文件删除
默认情况下随Java进程的结束而销毁
3、文件更新
-XX:PerfDataSamplingInterval = 50ms
即内存与PerfData文件的数据延迟为50ms
纯Java编写
\openjdk\jdk\src\share\classes\sun\tools\jstat\Jstat.java
3、jinfo
4、jstack
5、jmap
6、jconsole
7、visualVM
8、arthas
Java agent
1、命令行
2、attach
实战
1、统计线程数
1 | jstack -l 6972 | grep 'java.lang.Thread.State' | wc -l |
2、检测死锁
可使用jstack、jconsle、visualVM
3、CPU占用过高
- 定位到占用CPU最高的进程
1 | top -H -p 6290 |
线程ID由十进制转成十六进制,用Python
jstack 6290(进程ID)|grep 18a1(线程ID,十六进制) -A 30
问题:
模拟OOM并思考如何调优
死锁、CPU占用过高问题排查
Java Agent的两种实现方式自己写DEMO