linux下jmap,jstat和jstack使用


剛好用到,轉自http://blog.csdn.net/sinat_29581293/article/details/70214436 有空再整理:

 

先jps -ml 

再sudo -u hive /usr/java/latest/bin/jstack 19661(此為進程號) > /tmp/jstack.txt

 

首先回顧下相關概念:

Java堆和棧的區別 

棧與堆都是Java用來在Ram中存放數據的地方。與C++不同,Java自動管理棧和堆,程序員不能直接地設置棧或堆。 
Java的堆是一個運行時數據區,類的對象從中分配空間。這些對象通過new、newarray、anewarray和 multianewarray等指令建立,它們不需要程序代碼來顯式的釋放。堆是由垃圾回收來負責的,堆的優勢是可以動態地分配內存大小,生存期也不必事先告訴編譯器,因為它是在運行時動態分配內存的,Java的垃圾收集器會自動收走這些不再使用的數據。但缺點是,由於要在運行時動態分配內存,存取速度較慢。 

棧的優勢是,存取速度比堆要快,僅次於寄存器,棧數據可以共享。但缺點是,存在棧中的數據大小與生存期必須是確定的,缺乏靈活性。 

棧中主要存放一些基本類型的變量(,int, short, long, byte, float, double, boolean, char)和對象句柄。 
棧有一個很重要的特殊性,就是存在棧中的數據可以共享。假設我們同時定義: 
int a = 3; 
int b = 3; 
編譯器先處理int a = 3;首先它會在棧中創建一個變量為a的引用,然后查找棧中是否有3這個值,如果沒找到,就將3存放進來,然后將a指向3。接着處理int b = 3;在創建完b的引用變量后,因為在棧中已經有3這個值,便將b直接指向3。這樣,就出現了a與b同時均指向3的情況。 
這時,如果再令a=4;那么編譯器會重新搜索棧中是否有4值,如果沒有,則將4存放進來,並令a指向4;如果已經有了,則直接將a指向這個地址。因此a值的改變不會影響到b的值。 
要注意這種數據的共享與兩個對象的引用同時指向一個對象的這種共享是不同的,因為這種情況a的修改並不會影響到b, 它是由編譯器完成的,它有利於節省空間。而一個對象引用變量修改了這個對象的內部狀態,會影響到另一個對象引用變量。

 

1.jstat

jstat -gcutil pid 5s

每隔5s監控一次內存回收情況

E 代表 Eden 區使用率;
O(Old)代表老年代使用率    ;
P(Permanent)代表永久代使用率;

CCS 壓縮使用比例

M 元空間(MetaspaceSize)已使用的占當前容量百分比
YGC(Young GC)代表Minor GC 次數;
YGCT代表Minor GC耗時;
FGC(Full GC)代表Full GC次數;
FGCT(Full GC)代表Full GC耗時;
GCT代表Minor & Full GC共計耗時。

 

A、 jps(Java Virtual Machine Process Status Tool)      

    jps主要用來輸出JVM中運行的進程狀態信息。語法格式如下:

jps [options] [hostid]

 

    如果不指定hostid就默認為當前主機或服務器。

    命令行參數選項說明如下:

  1.  
    -q 不輸出類名、Jar名和傳入main方法的參數
  2.  
    -m 輸出傳入main方法的參數
  3.  
    -l 輸出main類或Jar的全限名
  4.  
    -v 輸出傳入JVM的參數

 

   比如下面:

  1.  
    root@ubuntu:/# jps -m -l
  2.  
    2458 org.artifactory.standalone.main.Main /usr/local/artifactory-2.2.5/etc/jetty.xml
  3.  
    29920 com.sun.tools.hat.Main -port 9998 /tmp/dump.dat
  4.  
    3149 org.apache.catalina.startup.Bootstrap start
  5.  
    30972 sun.tools.jps.Jps -m -l
  6.  
    8247 org.apache.catalina.startup.Bootstrap start
  7.  
    25687 com.sun.tools.hat.Main -port 9999 dump.dat
  8.  
    21711 mrf-center.jar

 

 

B、 jstack

 jstack -F pid 檢查是否有死鎖

    jstack主要用來查看某個Java進程內的線程堆棧信息。語法格式如下:

  1.  
    jstack [option] pid
  2.  
    jstack [option] executable core
  3.  
    jstack [option] [server-id@]remote-hostname-or-ip

    命令行參數選項說明如下:

  1.  
    -l long listings,會打印出額外的鎖信息,在發生死鎖時可以用jstack -l pid來觀察鎖持有情況
  2.  
    -m mixed mode,不僅會輸出Java堆棧信息,還會輸出C/C++堆棧信息(比如Native方法)

    jstack可以定位到線程堆棧,根據堆棧信息我們可以定位到具體代碼,所以它在JVM性能調優中使用得非常多。下面我們來一個實例找出某個Java進程中最耗費CPU的Java線程並定位堆棧信息,用到的命令有ps、top、printf、jstack、grep。

    第一步先找出Java進程ID,我部署在服務器上的Java應用名稱為mrf-center:

  1.  
    root@ubuntu:/# ps -ef | grep mrf-center | grep -v grep
  2.  
    root     21711     1  1 14:47 pts/3    00:02:10 java -jar mrf-center.jar

    得到進程ID為21711,第二步找出該進程內最耗費CPU的線程,可以使用ps -Lfp pid或者ps -mp pid -o THREAD, tid, time或者top -Hp pid,我這里用第三個,輸出如下:

JVM性能調優監控工具jps、jstack、jmap、jhat、jstat使用詳解

    TIME列就是各個Java線程耗費的CPU時間,CPU時間最長的是線程ID為21742的線程,用

printf "%x\n" 21742

 

    得到21742的十六進制值為54ee,下面會用到。    

    OK,下一步終於輪到jstack上場了,它用來輸出進程21711的堆棧信息,然后根據線程ID的十六進制值grep,如下:

  1.  
    root@ubuntu:/# jstack 21711 | grep 54ee
  2.  
    "PollIntervalRetrySchedulerThread" prio=10 tid=0x00007f950043e000 nid=0x54ee in Object.wait() [0x00007f94c6eda000]

 

    可以看到CPU消耗在PollIntervalRetrySchedulerThread這個類的Object.wait(),我找了下我的代碼,定位到下面的代碼:

[java] view plain copy

 
 

 

  1. // Idle wait  
  2. getLog().info("Thread [" + getName() + "] is idle waiting...");  
  3. schedulerThreadState = PollTaskSchedulerThreadState.IdleWaiting;  
  4. long now = System.currentTimeMillis();  
  5. long waitTime = now + getIdleWaitTime();  
  6. long timeUntilContinue = waitTime - now;  
  7. synchronized(sigLock) {  
  8.     try {  
  9.         if(!halted.get()) {  
  10.             sigLock.wait(timeUntilContinue);  
  11.         }  
  12.     }   
  13.     catch (InterruptedException ignore) {  
  14.     }  
  15. }  

 

    它是輪詢任務的空閑等待代碼,上面的sigLock.wait(timeUntilContinue)就對應了前面的Object.wait()。

 

C、 jmap(Memory Map)和jhat(Java Heap Analysis Tool)

    jmap用來查看堆內存使用狀況,一般結合jhat使用。

    jmap語法格式如下:

  1.  
    jmap [option] pid
  2.  
    jmap [option] executable core
  3.  
    jmap [option] [server-id@]remote-hostname-or-ip

 

    如果運行在64位JVM上,可能需要指定-J-d64命令選項參數。

jmap -permstat pid

 

    打印進程的類加載器和類加載器加載的持久代對象信息,輸出:類加載器名稱、對象是否存活(不可靠)、對象地址、父類加載器、已加載的類大小等信息,如下圖:

JVM性能調優監控工具jps、jstack、jmap、jhat、jstat使用詳解

   使用jmap -heap pid查看進程堆內存使用情況,包括使用的GC算法、堆配置參數和各代中堆內存使用情況。比如下面的例子:

  1.  
    root@ubuntu:/# jmap -heap 21711
  2.  
    Attaching to process ID 21711, please wait...
  3.  
    Debugger attached successfully.
  4.  
    Server compiler detected.
  5.  
    JVM version is 20.10-b01
  6.  
     
  7.  
    using thread-local object allocation.
  8.  
    Parallel GC with 4 thread(s)
  9.  
     
  10.  
    Heap Configuration:
  11.  
       MinHeapFreeRatio = 40
  12.  
       MaxHeapFreeRatio = 70
  13.  
       MaxHeapSize      = 2067791872 (1972.0MB)
  14.  
       NewSize          = 1310720 (1.25MB)
  15.  
       MaxNewSize       = 17592186044415 MB
  16.  
       OldSize          = 5439488 (5.1875MB)
  17.  
       NewRatio         = 2
  18.  
       SurvivorRatio    = 8
  19.  
       PermSize         = 21757952 (20.75MB)
  20.  
       MaxPermSize      = 85983232 (82.0MB)
  21.  
     
  22.  
    Heap Usage:
  23.  
    PS Young Generation
  24.  
    Eden Space:
  25.  
       capacity = 6422528 (6.125MB)
  26.  
       used     = 5445552 (5.1932830810546875MB)
  27.  
       free     = 976976 (0.9317169189453125MB)
  28.  
       84.78829520089286% used
  29.  
    From Space:
  30.  
       capacity = 131072 (0.125MB)
  31.  
       used     = 98304 (0.09375MB)
  32.  
       free     = 32768 (0.03125MB)
  33.  
       75.0% used
  34.  
    To Space:
  35.  
       capacity = 131072 (0.125MB)
  36.  
       used     = 0 (0.0MB)
  37.  
       free     = 131072 (0.125MB)
  38.  
       0.0% used
  39.  
    PS Old Generation
  40.  
       capacity = 35258368 (33.625MB)
  41.  
       used     = 4119544 (3.9287033081054688MB)
  42.  
       free     = 31138824 (29.69629669189453MB)
  43.  
       11.683876009235595% used
  44.  
    PS Perm Generation
  45.  
       capacity = 52428800 (50.0MB)
  46.  
       used     = 26075168 (24.867218017578125MB)
  47.  
       free     = 26353632 (25.132781982421875MB)
  48.  
       49.73443603515625% used
  49.  
       ....

 

    使用jmap -histo[:live] pid查看堆內存中的對象數目、大小統計直方圖,如果帶上live則只統計活對象,如下:

  1.  
    root@ubuntu:/# jmap -histo:live 21711 | more
  2.  
     
  3.  
     num     #instances         #bytes  class name
  4.  
    ----------------------------------------------
  5.  
       1:         38445        5597736  <constMethodKlass>
  6.  
       2:         38445        5237288  <methodKlass>
  7.  
       3:          3500        3749504  <constantPoolKlass>
  8.  
       4:         60858        3242600  <symbolKlass>
  9.  
       5:          3500        2715264  <instanceKlassKlass>
  10.  
       6:          2796        2131424  <constantPoolCacheKlass>
  11.  
       7:          5543        1317400  [I
  12.  
       8:         13714        1010768  [C
  13.  
       9:          4752        1003344  [B
  14.  
      10:          1225         639656  <methodDataKlass>
  15.  
      11:         14194         454208  java.lang.String
  16.  
      12:          3809         396136  java.lang.Class
  17.  
      13:          4979         311952  [S
  18.  
      14:          5598         287064  [[I
  19.  
      15:          3028         266464  java.lang.reflect.Method
  20.  
      16:           280         163520  <objArrayKlassKlass>
  21.  
      17:          4355         139360  java.util.HashMap$Entry
  22.  
      18:          1869         138568  [Ljava.util.HashMap$Entry;
  23.  
      19:          2443          97720  java.util.LinkedHashMap$Entry
  24.  
      20:          2072          82880  java.lang.ref.SoftReference
  25.  
      21:          1807          71528  [Ljava.lang.Object;
  26.  
      22:          2206          70592  java.lang.ref.WeakReference
  27.  
      23:           934          52304  java.util.LinkedHashMap
  28.  
      24:           871          48776  java.beans.MethodDescriptor
  29.  
      25:          1442          46144  java.util.concurrent.ConcurrentHashMap$HashEntry
  30.  
      26:           804          38592  java.util.HashMap
  31.  
      27:           948          37920  java.util.concurrent.ConcurrentHashMap$Segment
  32.  
      28:          1621          35696  [Ljava.lang.Class;
  33.  
      29:          1313          34880  [Ljava.lang.String;
  34.  
      30:          1396          33504  java.util.LinkedList$Entry
  35.  
      31:           462          33264  java.lang.reflect.Field
  36.  
      32:          1024          32768  java.util.Hashtable$Entry
  37.  
      33:           948          31440  [Ljava.util.concurrent.ConcurrentHashMap$HashEntry;

 

    class name是對象類型,說明如下:

  1.  
    B  byte
  2.  
    C  char
  3.  
    D  double
  4.  
    F  float
  5.  
    I  int
  6.  
    J  long
  7.  
    Z  boolean
  8.  
    [  數組,如[I表示int[]
  9.  
    [L+類名 其他對象

 

    還有一個很常用的情況是:用jmap把進程內存使用情況dump到文件中,再用jhat分析查看。jmap進行dump命令格式如下:

jmap -dump:format=b,file=dumpFileName

 

    我一樣地對上面進程ID為21711進行Dump:

  1.  
    root@ubuntu:/# jmap -dump:format=b,file=/tmp/dump.dat 21711     
  2.  
    Dumping heap to /tmp/dump.dat ...
  3.  
    Heap dump file created

 

   dump出來的文件可以用MAT、VisualVM等工具查看,這里用jhat查看:

  1.  
    root@ubuntu:/# jhat -port 9998 /tmp/dump.dat
  2.  
    Reading from /tmp/dump.dat...
  3.  
    Dump file created Tue Jan 28 17:46:14 CST 2014
  4.  
    Snapshot read, resolving...
  5.  
    Resolving 132207 objects...
  6.  
    Chasing references, expect 26 dots..........................
  7.  
    Eliminating duplicate references..........................
  8.  
    Snapshot resolved.
  9.  
    Started HTTP server on port 9998
  10.  
    Server is ready.

 

     然后就可以在瀏覽器中輸入主機地址:9998查看了:

JVM性能調優監控工具jps、jstack、jmap、jhat、jstat使用詳解

    上面紅線框出來的部分大家可以自己去摸索下,最后一項支持OQL(對象查詢語言)。

 

D、jstat(JVM統計監測工具)

    語法格式如下:

jstat [ generalOption | outputOptions vmid [interval[s|ms] [count]] ]

 

    vmid是虛擬機ID,在Linux/Unix系統上一般就是進程ID。interval是采樣時間間隔。count是采樣數目。比如下面輸出的是GC信息,采樣時間間隔為250ms,采樣數為4:

  1.  
    root@ubuntu:/# jstat -gc 21711 250 4
  2.  
     S0C    S1C    S0U    S1U      EC       EU        OC         OU       PC     PU    YGC     YGCT    FGC    FGCT     GCT   
  3.  
    192.0  192.0   64.0   0.0    6144.0   1854.9   32000.0     4111.6   55296.0 25472.7    702    0.431   3      0.218    0.649
  4.  
    192.0  192.0   64.0   0.0    6144.0   1972.2   32000.0     4111.6   55296.0 25472.7    702    0.431   3      0.218    0.649
  5.  
    192.0  192.0   64.0   0.0    6144.0   1972.2   32000.0     4111.6   55296.0 25472.7    702    0.431   3      0.218    0.649
  6.  
    192.0  192.0   64.0   0.0    6144.0   2109.7   32000.0     4111.6   55296.0 25472.7    702    0.431   3      0.218    0.649

 

    要明白上面各列的意義,先看JVM堆內存布局:

JVM性能調優監控工具jps、jstack、jmap、jhat、jstat使用詳解

    可以看出:

  1.  
    堆內存 = 年輕代 + 年老代 + 永久代
  2.  
    年輕代 = Eden區 + 兩個Survivor區(From和To)

 

    現在來解釋各列含義:

  1.  
    S0C、S1C、S0U、S1U:Survivor 0/1區容量(Capacity)和使用量(Used)
  2.  
    EC、EU:Eden區容量和使用量
  3.  
    OC、OU:年老代容量和使用量
  4.  
    PC、PU:永久代容量和使用量
  5.  
    YGC、YGT:年輕代GC次數和GC耗時
  6.  
    FGC、FGCT:Full GC次數和Full GC耗時
  7.  
    GCT:GC總耗時

 

 

其他JVM性能調優參考資料:

《Java虛擬機規范》

《Java Performance》

《Trouble Shooting Guide for JavaSE 6 with HotSpot VM》: http://www.oracle.com/technetwork/java/javase/tsg-vm-149989.pdf 

《Effective Java》

VisualVM: http://docs.oracle.com/javase/7/docs/technotes/guides/visualvm/

jConsole: http://docs.oracle.com/javase/1.5.0/docs/guide/management/jconsole.html

Monitoring and Managing JavaSE 6 Applications: http://www.oracle.com/technetwork/articles/javase/monitoring-141801.html

來自: http://my.oschina.net/feichexia/blog/196575

 

jstack信息分析

 

[java] view plain copy

 
 

 

  1. 2017-04-17 17:45:39  
  2. Full thread dump Java HotSpot(TM) 64-Bit Server VM (24.71-b01 mixed mode):  
  3.   
  4. "Attach Listener" daemon prio=10 tid=0x00007f75a4001000 nid=0x947 waiting on condition [0x0000000000000000]  
  5.    java.lang.Thread.State: RUNNABLE  
  6.   
  7. "LeaseRenewer:hive@nameservice1" daemon prio=10 tid=0x00007f7364f5a000 nid=0x537 waiting on condition [0x00007f713407f000]  
  8.    java.lang.Thread.State: TIMED_WAITING (sleeping)  
  9.     at java.lang.Thread.sleep(Native Method)  
  10.     at org.apache.hadoop.hdfs.LeaseRenewer.run(LeaseRenewer.java:438)  
  11.     at org.apache.hadoop.hdfs.LeaseRenewer.access$700(LeaseRenewer.java:71)  
  12.     at org.apache.hadoop.hdfs.LeaseRenewer$1.run(LeaseRenewer.java:298)  
  13.     at java.lang.Thread.run(Thread.java:745)  
  14.   
  15. "HiveServer2-Handler-Pool: Thread-883126" prio=10 tid=0x00007f73bc016000 nid=0x4e5 waiting on condition [0x00007f7137bba000]  
  16.    java.lang.Thread.State: TIMED_WAITING (parking)  
  17.     at sun.misc.Unsafe.park(Native Method)  
  18.     - parking to wait for  <0x00000006585a35d8> (a java.util.concurrent.SynchronousQueue$TransferStack)  
  19.     at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:226)  
  20.     at java.util.concurrent.SynchronousQueue$TransferStack.awaitFulfill(SynchronousQueue.java:460)  
  21.     at java.util.concurrent.SynchronousQueue$TransferStack.transfer(SynchronousQueue.java:359)  
  22.     at java.util.concurrent.SynchronousQueue.poll(SynchronousQueue.java:942)  
  23.     at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1068)  
  24.     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)  
  25.     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)  
  26.     at java.lang.Thread.run(Thread.java:745)  
  27.   
  28. "IPC Parameter Sending Thread #729" daemon prio=10 tid=0x00007f7364f59000 nid=0x73cc waiting on condition [0x00007f712c302000]  
  29.    java.lang.Thread.State: TIMED_WAITING (parking)  
  30.     at sun.misc.Unsafe.park(Native Method)  
  31.     - parking to wait for  <0x0000000656680e10> (a java.util.concurrent.SynchronousQueue$TransferStack)  
  32.     at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:226)  
  33.     at java.util.concurrent.SynchronousQueue$TransferStack.awaitFulfill(SynchronousQueue.java:460)  
  34.     at java.util.concurrent.SynchronousQueue$TransferStack.transfer(SynchronousQueue.java:359)  
  35.     at java.util.concurrent.SynchronousQueue.poll(SynchronousQueue.java:942)  
  36.     at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1068)  
  37.     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)  
  38.     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)  
  39.     at java.lang.Thread.run(Thread.java:745)  
  40.   
  41. "HiveServer2-Handler-Pool: Thread-882656" prio=10 tid=0x00007f73bc013000 nid=0x497a waiting on condition [0x00007f712cc0b000]  
  42.    java.lang.Thread.State: TIMED_WAITING (parking)  
  43.     at sun.misc.Unsafe.park(Native Method)  
  44.     - parking to wait for  <0x00000006585a35d8> (a java.util.concurrent.SynchronousQueue$TransferStack)  
  45.     at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:226)  
  46.     at java.util.concurrent.SynchronousQueue$TransferStack.awaitFulfill(SynchronousQueue.java:460)  
  47.     at java.util.concurrent.SynchronousQueue$TransferStack.transfer(SynchronousQueue.java:359)  
  48.     at java.util.concurrent.SynchronousQueue.poll(SynchronousQueue.java:942)  
  49.     at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1068)  
  50.     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)  
  51.     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)  
  52.     at java.lang.Thread.run(Thread.java:745)  
  53.   
  54. "qtp931145444-882653" daemon prio=10 tid=0x00007f747401c000 nid=0x3376 waiting on condition [0x00007f7137dbc000]  
  55.    java.lang.Thread.State: TIMED_WAITING (parking)  
  56.     at sun.misc.Unsafe.park(Native Method)  
  57.     - parking to wait for  <0x0000000657459540> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)  
  58.     at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:226)  
  59.     at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2082)  
  60.     at org.eclipse.jetty.util.BlockingArrayQueue.poll(BlockingArrayQueue.java:342)  
  61.     at org.eclipse.jetty.util.thread.QueuedThreadPool.idleJobPoll(QueuedThreadPool.java:526)  
  62.     at org.eclipse.jetty.util.thread.QueuedThreadPool.access$600(QueuedThreadPool.java:44)  
  63.     at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:572)  
  64.     at java.lang.Thread.run(Thread.java:745)  
  65.   
  66. "qtp931145444-882456" daemon prio=10 tid=0x00007f7470001000 nid=0x9600 waiting on condition [0x00007f7133776000]  
  67.    java.lang.Thread.State: TIMED_WAITING (parking)  
  68.     at sun.misc.Unsafe.park(Native Method)  
  69.     - parking to wait for  <0x0000000657459540> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)  
  70.     at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:226)  
  71.     at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2082)  
  72.     at org.eclipse.jetty.util.BlockingArrayQueue.poll(BlockingArrayQueue.java:342)  
  73.     at org.eclipse.jetty.util.thread.QueuedThreadPool.idleJobPoll(QueuedThreadPool.java:526)  
  74.     at org.eclipse.jetty.util.thread.QueuedThreadPool.access$600(QueuedThreadPool.java:44)  
  75.     at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:572)  
  76.     at java.lang.Thread.run(Thread.java:745)  
  77.   
  78. "qtp931145444-882454" daemon prio=10 tid=0x00007f7454005800 nid=0x8ca1 waiting on condition [0x00007f713508f000]  
  79.    java.lang.Thread.State: TIMED_WAITING (parking)  
  80.     at sun.misc.Unsafe.park(Native Method)  
  81.     - parking to wait for  <0x0000000657459540> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)  
  82.     at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:226)  
  83.     at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2082)  
  84.     at org.eclipse.jetty.util.BlockingArrayQueue.poll(BlockingArrayQueue.java:342)  
  85.     at org.eclipse.jetty.util.thread.QueuedThreadPool.idleJobPoll(QueuedThreadPool.java:526)  
  86.     at org.eclipse.jetty.util.thread.QueuedThreadPool.access$600(QueuedThreadPool.java:44)  
  87.     at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:572)  
  88.     at java.lang.Thread.run(Thread.java:745)  
  89.   
  90. "qtp931145444-881328" daemon prio=10 tid=0x00007f746c001800 nid=0x184c waiting on condition [0x00007f713306f000]  
  91.    java.lang.Thread.State: TIMED_WAITING (parking)  
  92.     at sun.misc.Unsafe.park(Native Method)  
  93.     - parking to wait for  <0x0000000657459540> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)  
  94.     at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:226)  
  95.     at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2082)  
  96.     at org.eclipse.jetty.util.BlockingArrayQueue.poll(BlockingArrayQueue.java:342)  
  97.     at org.eclipse.jetty.util.thread.QueuedThreadPool.idleJobPoll(QueuedThreadPool.java:526)  
  98.     at org.eclipse.jetty.util.thread.QueuedThreadPool.access$600(QueuedThreadPool.java:44)  
  99.     at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:572)  
  100.     at java.lang.Thread.run(Thread.java:745)  
  101.   
  102. "pool-68894-thread-1" prio=10 tid=0x00007f73649a1800 nid=0x6d7 waiting on condition [0x00007f7130544000]  
  103.    java.lang.Thread.State: TIMED_WAITING (parking)  
  104.     at sun.misc.Unsafe.park(Native Method)  
  105.     - parking to wait for  <0x00000006c5af6798> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)  
  106.     at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:226)  
  107.     at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2082)  
  108.     at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1090)  
  109.     at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:807)  
  110.     at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1068)  
  111.     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)  
  112.     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)  
  113.     at java.lang.Thread.run(Thread.java:745)  

 

各狀態說明:

New: 當線程對象創建時存在的狀態,此時線程不可能執行;

Runnable:當調用thread.start()后,線程變成為Runnable狀態。只要得到CPU,就可以執行;

Running:線程正在執行;

Waiting:執行thread.join()或在鎖對象調用obj.wait()等情況就會進該狀態,表明線程正處於等待某個資源或條件發生來喚醒自己;

Timed_Waiting:執行Thread.sleep(long)、thread.join(long)或obj.wait(long)等就會進該狀態,與Waiting的區別在於Timed_Waiting的等待有時間限制;

Blocked:如果進入同步方法或同步代碼塊,沒有獲取到鎖,則會進入該狀態;

Dead:線程執行完畢,或者拋出了未捕獲的異常之后,會進入dead狀態,表示該線程結束

其次,對於jstack日志,我們要着重關注如下關鍵信息

Deadlock:表示有死鎖

Waiting on condition:等待某個資源或條件發生來喚醒自己。具體需要結合jstacktrace來分析,比如線程正在sleep,網絡讀寫繁忙而等待

Blocked:阻塞

Waiting on monitor entry:在等待獲取鎖

in Object.wait():獲取鎖后又執行obj.wait()放棄鎖

對於Waiting on monitor entry 和 in Object.wait()的詳細描述:Monitor是 Java中用以實現線程之間的互斥與協作的主要手段,它可以看成是對象或者 Class的鎖。每一個對象都有,也僅有一個 monitor。從下圖中可以看出,每個 Monitor在某個時刻,只能被一個線程擁有,該線程就是 "Active Thread",而其它線程都是 "Waiting Thread",分別在兩個隊列 " Entry Set"和 "Wait Set"里面等候。在 "Entry Set"中等待的線程狀態是 "Waiting for monitor entry",而在 "Wait Set"中等待的線程狀態是 "in Object.wait()"

 

 

 

總結:

 

對於jstack日志,我們要着重關注如下關鍵信息

Deadlock:表示有死鎖

Waiting on condition:等待某個資源或條件發生來喚醒自己。具體需要結合jstacktrace來分析,比如線程正在sleep,網絡讀寫繁忙而等待

Blocked:阻塞

Waiting on monitor entry:在等待獲取鎖

 

如果說系統慢,那么要特別關注Blocked,Waiting on condition

如果說系統的cpu耗的高,那么肯定是線程執行有死循環,那么此時要關注下Runable狀態。

http://blog.csdn.net/zxh87/article/details/52137335


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM