java内存溢出排查jstack_Java命令行监控工具(jmap,jstack,jstat,jinfo,jps)
項(xiàng)目部署上線之后,線上項(xiàng)目是不能輕易修改的,定位問題的難度也會(huì)變大。因此監(jiān)控是非常重要的一個(gè)環(huán)節(jié),有了監(jiān)控,我們才能更好的定位系統(tǒng)中的問題,從而排查。監(jiān)控的工具有很多種, 但是java自帶的命令行監(jiān)控工具,是必須要掌握的。
jps
查看系統(tǒng)中jvm進(jìn)程, 其它的命令通常先使用jps查看進(jìn)程號(hào),然后在根據(jù)線程號(hào)獲取jvm進(jìn)程信息
image.png
jps -m 查看jvm進(jìn)程并且?guī)в袇?shù)查看
jps -v 查看傳遞到j(luò)vm的參數(shù)
jstat
顯示JVM的性能統(tǒng)計(jì)信息,
常見用法:jstat - [-t] [-h] [ []]
例如:查看JIT編譯信息,GC信息和JVM中的class信息。
image.png
解釋下-gc選項(xiàng)中列的含義:-gc查看垃圾收集器中的信息, 主要包含jvm的運(yùn)行時(shí)數(shù)據(jù)區(qū)統(tǒng)計(jì)。
后綴為C的代表當(dāng)前區(qū)的容量,后綴為U的代表已經(jīng)使用了多少容量,后綴為T的代表耗時(shí)
S0C 存活區(qū)0的容量(KB)
S1C 存活區(qū)1的容量(KB)
S0U 存活區(qū)0使用的空間 (KB).
S1U 存活區(qū)1的利用空間 (KB).
EC Eden區(qū)的容量(KB).
EU Eden區(qū)利用的容量(KB).
OC 老年代容量(KB).
OU 老年代使用容量(KB).
PC 當(dāng)前永久帶的容量(KB).
PU 永久帶使用容量(KB).
YGC 發(fā)生了多少次Young GC
YGCT Young GC的時(shí)間
FGC Full GC的次數(shù)
FGCT Full GC的收集時(shí)間
GCT 總共的GC時(shí)間.
jstack
查看線程堆棧信息,在發(fā)生死鎖的時(shí)候可以利用這個(gè)命令查找死鎖或者在發(fā)生死循環(huán)的時(shí)候利用此命令排查。
jstack vmpid 會(huì)打印線程的堆棧信息。通過堆棧可以查看具體線程正在執(zhí)行那些代碼,廈門演示兩個(gè)使用jstack排查死鎖與死循環(huán)的命令。
死鎖代碼:
public class DeadLock {
private static Object o1 = new Object();
private static Object o2 = new Object();
private static CountDownLatch countDownLatch = new CountDownLatch(2);
public static void main(String[] args) throws InterruptedException {
new Thread(){
@Override
public void run() {
synchronized (o1){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("線程1 獲得鎖1");
synchronized (o2){
System.out.println("線程1 獲得鎖2");
countDownLatch.countDown();
}
}
}
}.start();
new Thread(){
@Override
public void run() {
synchronized (o2){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("線程2 獲得鎖2");
synchronized (o1){
System.out.println("線程2 獲得鎖1");
countDownLatch.countDown();
}
}
}
}.start();
countDownLatch.await();
System.out.println("執(zhí)行完畢");
}
}
死鎖之后:
可以看到j(luò)stack已經(jīng)幫我們找到了死鎖。
image.png
image.png
死循環(huán)需要配合Top命令一起使用,死循環(huán)會(huì)導(dǎo)致CPU不斷的飆升,這時(shí)候使用top命令,查看cpu占用率較高的命令:
image.png
使用top -H -p 24278 查看進(jìn)程中具體是那一條線程的CPU利用率高
image.png
可以看到是24279的線程,在top中使用的是10進(jìn)制,在jstack中打印的線程是16進(jìn)制,因此做一次轉(zhuǎn)換。
24279 => 5ed7
然后查看線程:
image.png
然后我們可以知道具體那一行的指令在一直運(yùn)行。
jinfo查看JVM啟動(dòng)時(shí)候設(shè)置的參數(shù)值
jinfo可以查看當(dāng)前JVM線程配置的系統(tǒng)屬性,以及運(yùn)行時(shí)設(shè)置的參數(shù)值。
直接使用jinfo
前半段是系統(tǒng)的屬性
image.png
后半段是jvm的參數(shù)
image.png
我們也可以直接使用jinfo查看具體的某個(gè)參數(shù)值:
image.png
jmap分析堆
在發(fā)生OME的時(shí)候,會(huì)用jmap分析堆中具體是什么問題,才能更好的解決問題。jmap一般和mat配合使用。
一般在java開發(fā)的項(xiàng)目啟動(dòng)時(shí)候,最好加上下面命令,在內(nèi)存溢出的時(shí)候可以通過日志查看信息。
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/java/dump
當(dāng)然在項(xiàng)目運(yùn)行的時(shí)候也可以使用jmap -heap jvmpid查看對象內(nèi)存的映射。
演示內(nèi)存溢出
堆內(nèi)存溢出代碼
public class DealCycle {
public static LinkedList linkedList = new LinkedList<>();
public static void main(String[] args) {
int i = 0;
while (true){
linkedList.add(i);
}
}
}
運(yùn)行:
image.png
大家可以去網(wǎng)站上下載java mat的二進(jìn)制壓縮包,學(xué)習(xí)一下
image.png
image.png
如果每次都等到內(nèi)存溢出才導(dǎo)出文件時(shí)間就有些晚了,可以使用jmap直接導(dǎo)出
image.png
最后
這篇文章主要介紹了java自帶的命令行工具,通過這些命令行工具,我們可以很好的得知當(dāng)前jvm的運(yùn)行狀態(tài)。
總結(jié)
以上是生活随笔為你收集整理的java内存溢出排查jstack_Java命令行监控工具(jmap,jstack,jstat,jinfo,jps)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java无向图代码实例_Java 图示例
- 下一篇: matebook14支持触摸屏吗_华为M