前言
首先建議先簡單瞭解JVM的內存機制,以及GC垃圾回收機制
初步瞭解jvm的內存分配,gc以及簡單的jvm內存配置
以下j開頭的命令基本都是java命令,如果沒有設置全局環境變量,需要加上${java_home}
全路徑。如/usr/local/jdk8/java/bin/jmap pid
一、內存不足
1. 查看pid
ps -ef|grep java
或
jps -lv
24130 就是pid
2. jmap -heap查看堆內存
jmap -heap pid
上面就是jvm的堆內存配置信息,以及新生代,老年代,永久代的內存最大值和當前使用值
3. jmap -histo:live
這裏會觸發Full GC
jmap -histo:live :打印每個class的實例數⽬、內存佔用、類全名信息
jmap -histo:live pid > 1.txt
然後查看1.txt
less 1.txt
或者cat 1.txt
4. jmap -dump:live
同樣會觸發Full GC
jmap -dump:live,format=b,file=heap.bin <pid>:將當前存活對象dump到⽂件
可以導入到本地的jvisual進行分析,這個工具在jdk的java/bin目錄下
可以查看類的實例數和所佔內存大小,分析哪個類異常
二、cpu飆升
1. top命令
top命令查看cpu,內存情況
top
找到佔用cpu高的pid
top -Hp pid
再找出佔用高的pid
2. jstack查看對賬信息
假如通過Top命令,找到了佔用cpu高的java應用的pid是24130
那麼
jstack [-l] pid
-l是打印出線程信息
jstack -l 24130
假如我們上面 top -Hp 命令找到的佔用cpu高的pid是24190
先轉成16進制
printf "%x\n" s
printf “%x\n” 24190
然後
jstack -l javapid | grep '0x'+十六進制pid -A10 --color
-A是打印符合條件後n行,-C是環繞n行,-B是之前n行
jstack -l 24130|grep ‘0x5e7e’ -A10 --color
根據堆棧信息和線程狀態,分析cpu佔用原因。
如果線程狀態是BLOCKED,就是線程阻塞中
三、gc和類加載情況
1. jstat -class
jstat -class pid
- Loaded:加載class的數量
- Bytes:所佔用空間大小
- Unloaded:未加載數量
- Bytes:未加載佔用空間
- Time:時間s
編譯統計
jstat -compiler pid
2. jstat -gc
伊甸園區(Eden區)
倖存區(survivor區)
jstat -gc pid 1000
1000表示1秒刷新一次
S0C:第一個倖存區的大小
S1C:第二個倖存區的大小
S0U:第一個倖存區的使用大小
S1U:第二個倖存區的使用大小
EC:伊甸園區的大小
EU:伊甸園區的使用大小
OC:老年代大小
OU:老年代使用大小
MC:方法區大小
MU:方法區使用大小
CCSC:壓縮類空間大小
CCSU:壓縮類空間使用大小
YGC:年輕代垃圾回收次數
YGCT:年輕代垃圾回收消耗時間 ,秒
FGC:老年代垃圾回收次數
FGCT:老年代垃圾回收消耗時間 ,秒
GCT:垃圾回收消耗總時間 ,秒
總體垃圾回收統計
jstat -gcutil pid 1000
S0:倖存1區當前使用比例
S1:倖存2區當前使用比例
E:伊甸園區使用比例
O:老年代使用比例
M:元數據區使用比例
CCS:壓縮使用比例
YGC:年輕代垃圾回收次數
FGC:老年代垃圾回收次數
FGCT:老年代垃圾回收消耗時間
GCT:垃圾回收消耗總時間
其他:
# 新生代垃圾回收統計
jstat -gcnew pid
#老年代垃圾回收統計
jstat -gcold pid
觀察
通過觀察YGC和FGC的次數和頻率,以及FGCT / FGC 單位耗時,YGCT / YGC 單位耗時,判斷內存是否足夠。
如果頻繁的FULL GC說明內存分配不合理。堆內存很可能分配太小了。並且GC會導致除了垃圾收集收集器線
程之外的線程都被掛起,頻繁GC毫無疑問是影響程序的
觀察Eden區的內存佔用和老年代的內存佔用,如果持續的增加說明很可能存在內存泄漏問題,可能導致OOM