欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java中工具Jstack的使用實(shí)例

 更新時(shí)間:2022年04月28日 16:35:23   作者:Mr_Yao  
jstack用于生成java虛擬機(jī)當(dāng)前時(shí)刻的線程快照,下面這篇文章主要給大家介紹了關(guān)于Java中工具Jstack使用的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下

jstack - Prints Java thread stack traces for a Java process, core file, or remote debug server.

Jstack 主要的作用是生成當(dāng)前進(jìn)程中所有線程的信息,也就是當(dāng)前時(shí)刻 JVM 的線程快照,通過線程的信息我們可以定位到程序中出現(xiàn)長時(shí)間停頓、CPU 占用率過高等問題。

線程快照中的信息是當(dāng)前 java 虛擬機(jī)內(nèi)每一條線程正在執(zhí)行的方法的堆棧集合,有了堆棧信息我們就可以分析出我們的程序問題出現(xiàn)在那,比如線程間死鎖、外部資源請求時(shí)間過長、死循環(huán)等。

使用:

jstack [ options ] pid
jstack [ options ] executable core
jstack [ options ] [ server-id@ ] remote-hostname-or-IP
OPTIONS
       -F
              Force a stack dump when jstack [-l] pid does not respond.
       -l
              Long listing. Prints additional information about locks such as a list of owned java.util.concurrent ownable synchronizers. See the
              AbstractOwnableSynchronizer class description at
              http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/locks/AbstractOwnableSynchronizer.html
       -m
              Prints a mixed mode stack trace that has both Java and native C/C++ frames.
  • -F 當(dāng)正常的請求不被響應(yīng)時(shí),強(qiáng)制輸出堆棧信息。
  • -l 額外打印鎖的信息,當(dāng)發(fā)生死鎖是可以查看鎖的信息
  • -m 如果調(diào)用本地方法棧的信息,可以打印 C/C++的堆棧

以一個(gè)發(fā)生死鎖的例子來看一下使用 Jstack 查看到的信息

public class Jstack {
    private static Object obj1 = new Object();
    private static Object obj2 = new Object();
    public static void main(String[] args) {
        new Thread(() -> {
            synchronized (obj1) {
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (obj2) {
                }
            }
        }).start();
        new Thread(() -> {
            synchronized (obj2) {
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (obj1) {
                }
            }
        }).start();
    }
}

上面代碼中,第一個(gè)線程拿到 obj1 的鎖,等待 obj2 的鎖,第二個(gè)線程拿到 obj2 的鎖,等待 obj1 的鎖,這樣就會發(fā)生死鎖。

先通過jps命令獲取到先拿到當(dāng)前的進(jìn)程 pid,然后通過 jstack 獲取線程的信息??梢钥吹接袃蓚€(gè)線程都處于阻塞狀態(tài)。

"Thread-1" #12 prio=5 os_prio=0 tid=0x00007fdff871c800 nid=0x3cc2 waiting for monitor entry [0x00007fdfce0fc000]
   java.lang.Thread.State: BLOCKED (on object monitor)
	at com.example.demo.jstack.Jstack.lambda$main$1(Jstack.java:36)
	- waiting to lock <0x000000076e925a90> (a java.lang.Object)
	- locked <0x000000076e925aa0> (a java.lang.Object)
	at com.example.demo.jstack.Jstack$$Lambda$2/2052001577.run(Unknown Source)
	at java.lang.Thread.run(Thread.java:748)

"Thread-0" #11 prio=5 os_prio=0 tid=0x00007fdff871a800 nid=0x3cc1 waiting for monitor entry [0x00007fdfce1fc000]
   java.lang.Thread.State: BLOCKED (on object monitor)
	at com.example.demo.jstack.Jstack.lambda$main$0(Jstack.java:25)
	- waiting to lock <0x000000076e925aa0> (a java.lang.Object)
	- locked <0x000000076e925a90> (a java.lang.Object)
	at com.example.demo.jstack.Jstack$$Lambda$1/1174361318.run(Unknown Source)
	at java.lang.Thread.run(Thread.java:748)

第一行顯示可線程名、線程優(yōu)先級、線程 id、線程狀態(tài)描述等信息

第二行顯示的是當(dāng)前線程的狀態(tài)

? Java 中線程的狀態(tài)分為 NEW、RUNNABLE、BLOCKED、WATING、TIMED_WATING、TERMINATED,但是在快照中 NEW 狀態(tài)是不會出現(xiàn)的。

再下面的就是當(dāng)前線程的調(diào)用棧的信息。調(diào)用棧中包含了鎖的信息。

? locked 表示使用 synchronized 申請對象鎖成功,監(jiān)視器的擁有者

? waiting to lock 表示使用 synchronized 申請對象鎖未成功,進(jìn)入等待區(qū)。

? waiting on 表示用 synchronized 申請對象鎖成功后,調(diào)用了 wait 方法,進(jìn)入對象的等待區(qū)等待。

? parking to wait for park 是基本的線程阻塞原語,不通過監(jiān)視器在對象上阻塞。隨 concurrent 包會出現(xiàn)的新的機(jī)制,與 synchronized 體系不同。

在最后也顯示出了代碼中出現(xiàn)死鎖的信息

Found one Java-level deadlock:
=============================
"Thread-1":
  waiting to lock monitor 0x00007fdfac006638 (object 0x000000076e925a90, a java.lang.Object),
  which is held by "Thread-0"
"Thread-0":
  waiting to lock monitor 0x00007fdfac003da8 (object 0x000000076e925aa0, a java.lang.Object),
  which is held by "Thread-1"

Java stack information for the threads listed above:
===================================================
"Thread-1":
	at com.example.demo.jstack.Jstack.lambda$main$1(Jstack.java:36)
	- waiting to lock <0x000000076e925a90> (a java.lang.Object)
	- locked <0x000000076e925aa0> (a java.lang.Object)
	at com.example.demo.jstack.Jstack$$Lambda$2/2052001577.run(Unknown Source)
	at java.lang.Thread.run(Thread.java:748)
"Thread-0":
	at com.example.demo.jstack.Jstack.lambda$main$0(Jstack.java:25)
	- waiting to lock <0x000000076e925aa0> (a java.lang.Object)
	- locked <0x000000076e925a90> (a java.lang.Object)
	at com.example.demo.jstack.Jstack$$Lambda$1/1174361318.run(Unknown Source)
	at java.lang.Thread.run(Thread.java:748)
Found 1 deadlock.

好了,熟悉了 Jstack,我們用一段死循環(huán)的代碼,通過 Jstack 來定位到使 CPU 占用 100%的代碼行

public class JstackDemo {
    public static Executor executor = Executors.newFixedThreadPool(3);
    private static Object lock = new Object();
    public static void main(String[] args) {
        Task task1 = new Task();
        Task task2 = new Task();
        executor.execute(task1);
        executor.execute(task2);
    }

    public static class Task implements Runnable {
        @Override
        public void run() {
            synchronized (lock) {
                run0();
            }
        }

        private void run0() {
            int i = 0;
            while (true) {
                i++;
            }
        }
    }
}

1、首先通過top查看到使 CPU 占用到 100%的進(jìn)程 id

2、使用top -Hp 進(jìn)程id 查看占用 CPU 最多的線程 id

3、將線程 id 轉(zhuǎn)換為 16 進(jìn)制

17997 -> 464d

4、使用 Jstack 查看 Java 所在的進(jìn)程,并找到相應(yīng)的線程

總結(jié)

到此這篇關(guān)于Java工具Jstack使用的文章就介紹到這了,更多相關(guān)Java工具Jstack使用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論