Jmap

查看内存信息,示例个数,占用内存大小

jmap -histo $pid #查看历史生成的实例
jmap -histo:live $pid #当前存活的实例,执行过程可能会触发一次full 过程

  1. num:序号
  2. instances:实例数量
  3. bytes:占用空间大小
  4. class name:类名称 [C = char[] [S = short[] [L = int [] [B = byte[] [I = int [][]

image.png

堆信息dump:
jmap -dump:format=b,file=eureka.hprof $pid #.hprof可以导入**jvisualvm**
jvm参数:
-XX:+HeapDumpOnOutOfMemoryError 内存溢出时,自动导出dump文件有可能导不出来
-XX:HeapDumapPath=./ 路径
image.png

Jstack

栈信息,线程相关的信息
image.png
可以用jvsualVm链接jvm 检查死锁,前提是远程启动是加参数

  1. java -Dcom.sun.management.jmxremote.port=8888 -Djava.rmi.server.hostname=192.168.65.60 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -jar microservice-eureka-server.jar
  2. PS

-Dcom.sun.management.jmxremote.port 为远程机器的JMX端口
-Djava.rmi.server.hostname 为远程机器IP
systemctl stop firewalld #临时关闭防火墙

image.png

jstack找出占用cpu最高的线程堆栈信息

  1. top -p pid :显示Java进程内存信息
    image.png
  2. 按H ,获取每个线程的内存情况
    image.png
  3. 找到最高的tid 19664,转为16进制 0x4cd0
  4. jstack pid | grep -A 10 4cd0 得到最后10行,查看原因
    image.png

Jinfo

jinfo -flags pid #查看正在运行的jvm 参数

image.png

jinfo -sysprops pid # 查看Java系统参数

image.png

Jstat

查看堆内存各部分的使用量,以及加载的类数量
jstat -[选项] [vmid] [间隔时间毫妙] [查询次数``]

示例:
评估程序内存使用以及GC压力整体情况

jstat -gc pid

  • S0C:第一个幸存区的大小,单位KB
  • S1C:第二个幸存区的大小
  • S0U:第一个幸存区的使用大小
  • S1U:第二个幸存区的使用大小
  • EC:伊甸园区的大小
  • EU:伊甸园区的使用大小
  • OC:老年代大小
  • OU:老年代使用大小
  • MC:方法区大小(元空间)
  • MU:方法区使用大小
  • CCSC:压缩类空间大小
  • CCSU:压缩类空间使用大小
  • YGC:年轻代垃圾回收次数
  • YGCT:年轻代垃圾回收消耗时间,单位s
  • FGC:老年代垃圾回收次数
  • FGCT:老年代垃圾回收消耗时间,单位s
  • GCT:垃圾回收消耗总时间,单位s

image.png
堆内存统计

jstat -gccapacity pid

  • NGCMN:新生代最小容量
  • NGCMX:新生代最大容量
  • NGC:当前新生代容量
  • S0C:第一个幸存区大小
  • S1C:第二个幸存区的大小
  • EC:伊甸园区的大小
  • OGCMN:老年代最小容量
  • OGCMX:老年代最大容量
  • OGC:当前老年代大小
  • OC:当前老年代大小
  • MCMN:最小元数据容量
  • MCMX:最大元数据容量
  • MC:当前元数据空间大小
  • CCSMN:最小压缩类空间大小
  • CCSMX:最大压缩类空间大小
  • CCSC:当前压缩类空间大小
  • YGC:年轻代gc次数
  • FGC:老年代GC次数

image.png
新生代垃圾回收统计

jstat -gcnew pid

  • NGCMN:新生代最小容量
  • NGCMX:新生代最大容量
  • NGC:当前新生代容量
  • S0CMX:最大幸存1区大小
  • S0C:当前幸存1区大小
  • S1CMX:最大幸存2区大小
  • S1C:当前幸存2区大小
  • ECMX:最大伊甸园区大小
  • EC:当前伊甸园区大小
  • YGC:年轻代垃圾回收次数
  • FGC:老年代回收次数

image.png
老年代垃圾回收统计

jstat -gcold pid

  • MC:方法区大小
  • MU:方法区使用大小
  • CCSC:压缩类空间大小
  • CCSU:压缩类空间使用大小
  • OC:老年代大小
  • OU:老年代使用大小
  • YGC:年轻代垃圾回收次数
  • FGC:老年代垃圾回收次数
  • FGCT:老年代垃圾回收消耗时间
  • GCT:垃圾回收消耗总时间

image.png
老年代内存统计

jstat -gcoldcapacity pid

  • OGCMN:老年代最小容量
  • OGCMX:老年代最大容量
  • OGC:当前老年代大小
  • OC:老年代大小
  • YGC:年轻代垃圾回收次数
  • FGC:老年代垃圾回收次数
  • FGCT:老年代垃圾回收消耗时间
  • GCT:垃圾回收消耗总时间

image.png
元空间统计

jstat -gcmetacapacity pid

  • MCMN:最小元数据容量
  • MCMX:最大元数据容量
  • MC:当前元数据空间大小
  • CCSMN:最小压缩类空间大小
  • CCSMX:最大压缩类空间大小
  • CCSC:当前压缩类空间大小
  • YGC:年轻代垃圾回收次数
  • FGC:老年代垃圾回收次数
  • FGCT:老年代垃圾回收消耗时间
  • GCT:垃圾回收消耗总时间

image.png

jstat -gcutil pid

  • S0:幸存1区当前使用比例
  • S1:幸存2区当前使用比例
  • E:伊甸园区使用比例
  • O:老年代使用比例
  • M:元数据区使用比例
  • CCS:压缩使用比例
  • YGC:年轻代垃圾回收次数
  • FGC:老年代垃圾回收次数
  • FGCT:老年代垃圾回收消耗时间
  • GCT:垃圾回收消耗总时间

image.png

JVM运行情况的估算思路

1:先通过 jstat gc -pid 计算关键数据
每秒产生多少对象
多久s区会满,minor gc的周期,

年轻代对象增长速率

jstat -gc pid 1000 10 #每1000ms执行一次,共执行10次
观察Eden区的使用来估算每秒新增了多少对象

YoungGC 触发的频率和每次的耗时

根据Eden的大小,和增长速度,推算minor gc多久
YoungGC 的凭据耗时计算: YGCT/YGC

估算每次minor gc 有多少对象存活,和多少进入老年代

每次 youngGC eden会变小,s区,老年代会变大,这个增长的就是youngGC后存活的
据此推断老年代对象的增长速度

Full gc 触发频率和每次耗时

耗时就算: FGCT/FGC
优化的思路:每次Young GC后的存活对象小于 S区的50%,尽量都留在年轻代。
减少FullGC

案例分析

Full Gc 导致卡顿的原因

  1. 先查看对应应用的jvm参数
  2. 画出 对应的内存模型
  3. jstat -gc pid 查看gc前后的内存变化
    计算每秒产生多少对象
    多久会占满 eden ,
    多久会有多少对象移至老年代,
    通常是老年代引起的Full gc

-Xms1536M -Xmx1536M -Xmn512M -Xss256K -XX:SurvivorRatio=6 -XX:MetaspaceSize=256M -XX:MaxMetaspaceSize=256M -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=75 -XX:+UseCMSInitiatingOccupancyOnly

image.png

minor gc 频率过高可以试着调整年轻代变大,
但是变大会出现的问题:可能出想大对象,在老年代内存担保,导致还是很老的对象进入老年代
导致老年代在增长
full gc比minor gc还多的原因有哪些?
1、元空间不够导致的多余full gc
2、显示调用System.gc()造成多余的full gc,这种一般线上尽量通过-XX:+DisableExplicitGC参数禁用,如果加上了这个JVM启动参数,那么代码中调用System.gc()没有任何效果
3、老年代空间分配担保机制

内存泄漏

JVM级缓存使用一个简单的Map,不断加入元素,导致map增大,在老年代占用,导致的full gc
最好使用 enCache框架, 带有LRU 算法的框架