JVM(Thread/Stack)

JVM Thread/Stack Memory Size

-Xss1024K

 

JVM Thread/Stack Object states

(6 states)java

new
    new Thread()
runnable
    java.lang.Thread.start()
blocked
    syncronized + java.lang.Object.wait()
waiting
    java.lang.Object.wait()
    java.lang.Thread.join()
    java.util.concurrent.locks.LockSupport.park()
timed_waiting  時間事後自動恢復
    java.lang.Thread.sleep(long time)
    java.lang.Object.wait(long timeout)
    java.lang.Thread.join(long millis)
    java.util.concurrent.locks.LockSupport.packNanos(long nanos)
    java.util.concurrent.locks.LockSupport.packUntil(long deadline)
terminated
    java.lang.Thread.start()方法結束,在內存中的Thread堆對象狀態。注意該Thread不能從新start()。

(對應OS的實際線程狀態爲: new ready running waiting terminated, ready+running=java's runnable)bash

 

JVM Thread/Stack Number

(JVM 8, at least 15 threads)jvm

6 no-Java System Threads
    VM Thread: 1
    VM  Periodic Task Thread:1
    GC task Thread#n (ParallelGC): 4
8 Java System Threads
    Reference Handler: 1
    Finalizer: 1
    Signal Dispatcher: 1
    C1 CompilerThreadn:1
    C2 CompilerThreadn:2
    Service Thread: 1
    Attach Listener: 1
1~n Java User Threads    
    * main:1
    * xxxxxx: 0~n

 

JVM Thread/Stack Structure

結構:{JVM Stack [Frame][Frame][Frame]... }
  • JVM Stack在每一個線程被建立時被建立,用來存放一組棧幀(StackFrame/Frame)
  • JVM Statck的大小能夠是固定的,也能夠是動態擴展的。
  • 若是線程須要一個比固定大小大的Stack,會發生StackOverflowError
  • 若是動態擴展Stack時沒有足夠的內存或者系統沒有足夠的內存爲新線程建立Stack,發生OutOfMemoryError。

 

JVM Thread/Stack Frame

結構:{Frame [ReturnValue] [LocalVariables[][][][]...] [OperandStack [][][]...] [ConstPoolRef] }

每次方法調用均會建立一個對應的Frame,方法執行完畢或者異常終止,Frame被銷燬。一個方法A調用另外一個方法B時,A的frame中止,新的frame被建立賦予B,執行完畢後,把計算結果傳遞給A,A繼續執行。spa

  • 返回值(Returen Value)
  • 局部變量表(Local Variables)
    • 局部變量表的大小在編譯期就被肯定。基元類型數據以及引用和返回地址(returnAddress)佔用一個局部變量大小,long/double須要兩個。

Java代碼:線程

int a=0;
int b=1;
int c=2;

對應的局部變量表:3d

LocalVariableTable: Start Length Slot Name Signature
                    2     12     0     a     I
                    4     10     1     b     I
                    6     8      2     c     I

局部變量表說明:code

Start: 變量偏移量。
Length: 做用域範圍長度。[Start,Start+Length)就是該變量的做用域。
Slot: 一個Slot能存儲32bit的數據類型、引用、返回地址,long/dobule須要兩個Slot
Name: 變量名
Signature: 字節碼簽名
  • 操做棧(Operand Stack)
    • Frame被建立時,操做棧是空的。操做棧的每一個項能夠存放JVM的各類類型數據,包括long/double。
    • 操做棧有個棧深,long/double貢獻兩個棧深。
    • 操做棧調用其它有返回結果的方法時,會把結果push到棧上。

Java代碼:對象

int a=1;
int b=2;
int c=a+b;

對應的指令:隊列

0: iconst_1 // push 1到操做棧。大於5的int值會用到 bipush <i> 指令。
1: istore_0 // pop 頂元素,存儲到index=0的本地變量。
2: iconst_2 // push 2 到操做棧
3: istore_1 // pop棧頂元素,存儲到index=1的本地變量。
4: iload_0  // 把index=0的本地變量加載到棧頂
5: iload_1  // 把index=1的本地變量加載到棧頂
6: iadd     // 把棧頂兩個數pop出來相加,並把結果存放到棧頂
7: istore_2 // 結果存儲到index=2的本地變量
  • 常量池引用(Const Pool Ref

 

Dump JVM Thread/Stack States(jstack/jconsole/jvisualvm/mat)

  • Thread/Stack狀態
    • runnable 運行中
      • java.lang.Thread.State: RUNNABLE
    • waiting on condition 等待資源
      • java.lang.Thread.State: RUNNABLE
      • java.lang.Thread.State: WAITING (parking)
      •  java.lang.Thread.State: TIMED_WAITING (parking)
    • Object.wait() 處於等待隊列裏的線程
      • java.lang.Thread.State: WAITING (on object monitor)
      • java.lang.Thread.State: TIMED_WAITING (on object monitor)
    • waiting on monitor entry 進入了臨界區,但等待獲取監視器
      • java.lang.Thread.State: BLOCKED (on object monitor)

Dump JVM Thread/Stack 線程/棧的運行快照    

Input(jstack/jconsole/jvisualvm/mat): ip

jstack jvm_pid
or
jstack -m jvm_pid

Output:

Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.102-b14 mixed mode):

"Attach Listener" #32 daemon prio=9 os_prio=0 tid=0x00007f490c001000 nid=0x2b70 waiting on condition [0x0000000000000000]
"RfbReceiverTask" #31 prio=6 os_prio=0 tid=0x00007f48e4168800 nid=0xdcd runnable [0x00007f48cbbfc000]
"RfbSenderTask" #30 prio=6 os_prio=0 tid=0x00007f48e4166800 nid=0xdcc waiting on condition [0x00007f48cbcfd000]
"Thread-3" #28 prio=6 os_prio=0 tid=0x00007f48e415c000 nid=0xdca waiting on condition [0x00007f4928377000]
"SwingWorker-pool-1-thread-6" #26 daemon prio=5 os_prio=0 tid=0x00007f48e4159000 nid=0xdc6 waiting on condition [0x00007f4928478000]
"SwingWorker-pool-1-thread-5" #25 daemon prio=5 os_prio=0 tid=0x00007f48e4157000 nid=0xdc5 waiting on condition [0x00007f4928579000]
"SwingWorker-pool-1-thread-4" #24 daemon prio=5 os_prio=0 tid=0x00007f48e4154000 nid=0xdad waiting on condition [0x00007f492867a000]
"SwingWorker-pool-1-thread-3" #23 daemon prio=5 os_prio=0 tid=0x00007f48e414d000 nid=0xd76 waiting on condition [0x00007f492877b000]
"SwingWorker-pool-1-thread-2" #21 daemon prio=5 os_prio=0 tid=0x00007f48e4147000 nid=0xb73 waiting on condition [0x00007f492887c000]
"SwingWorker-pool-1-thread-1" #20 daemon prio=5 os_prio=0 tid=0x00007f48e413f800 nid=0xb5f waiting on condition [0x00007f4928e7e000]
"Timer-0" #18 daemon prio=6 os_prio=0 tid=0x00007f48e40df800 nid=0xb49 in Object.wait() [0x00007f4928d7d000]
"DestroyJavaVM" #16 prio=5 os_prio=0 tid=0x00007f4948009800 nid=0xb35 waiting on condition [0x0000000000000000]
"AWT-EventQueue-0" #14 prio=6 os_prio=0 tid=0x00007f4948357000 nid=0xb47 waiting on condition [0x00007f4929d34000]
"AWT-Shutdown" #15 prio=5 os_prio=0 tid=0x00007f4948355800 nid=0xb46 in Object.wait() [0x00007f4929e35000]
"AWT-XAWT" #13 daemon prio=6 os_prio=0 tid=0x00007f4948321000 nid=0xb45 runnable [0x00007f492a136000]
"Java2D Disposer" #11 daemon prio=10 os_prio=0 tid=0x00007f4948300800 nid=0xb44 in Object.wait() [0x00007f492a64e000]
"TimerQueue" #10 daemon prio=5 os_prio=0 tid=0x00007f4948298000 nid=0xb43 waiting on condition [0x00007f492abe6000]
"Service Thread" #8 daemon prio=9 os_prio=0 tid=0x00007f494819a000 nid=0xb41 runnable [0x0000000000000000]
"C1 CompilerThread2" #7 daemon prio=9 os_prio=0 tid=0x00007f4948185000 nid=0xb40 waiting on condition [0x0000000000000000]
"C2 CompilerThread1" #6 daemon prio=9 os_prio=0 tid=0x00007f4948183000 nid=0xb3f waiting on condition [0x0000000000000000]
"C2 CompilerThread0" #5 daemon prio=9 os_prio=0 tid=0x00007f4948180000 nid=0xb3e waiting on condition [0x0000000000000000]
"Signal Dispatcher" #4 daemon prio=9 os_prio=0 tid=0x00007f494817e800 nid=0xb3d runnable [0x0000000000000000]
"Finalizer" #3 daemon prio=8 os_prio=0 tid=0x00007f494814b000 nid=0xb3c in Object.wait() [0x00007f493148d000]
"Reference Handler" #2 daemon prio=10 os_prio=0 tid=0x00007f4948146000 nid=0xb3b in Object.wait() [0x00007f493158e000]
"VM Thread" os_prio=0 tid=0x00007f494813e800 nid=0xb3a runnable 
"GC task thread#0 (ParallelGC)" os_prio=0 tid=0x00007f494801f000 nid=0xb36 runnable 
"GC task thread#1 (ParallelGC)" os_prio=0 tid=0x00007f4948020800 nid=0xb37 runnable 
"GC task thread#2 (ParallelGC)" os_prio=0 tid=0x00007f4948022800 nid=0xb38 runnable 
"GC task thread#3 (ParallelGC)" os_prio=0 tid=0x00007f4948024000 nid=0xb39 runnable 
"VM Periodic Task Thread" os_prio=0 tid=0x00007f49481ad000 nid=0xb42 waiting on condition

JVisualVM

JVM state -> JVisualVM show state
    BLOCKED -> Monitor
    RUNNABLE -> Running
    WAITING/TIMED_WAITING -> Sleeping/Park/Wait
    TERMINATED/NEW -> Zombie

JVisualVM show state
  Monitor: threads are waiting on a condition to become true to resume execution
  Running: thread is still running. 
  Sleeping: thread is sleeping (method yield() was called on the thread object)
  Wait: thread was blocked by a mutex or a barrier, and is waiting for another thread to release the lock
  Park: parked threads are suspended until they are given a permit. Unparking a thread is usually done by calling method unpark() on the thread object

Sleeping and Park are specific cases of (timed) waiting:
    Sleeping: specifically waiting in Thread.sleep().  
    Park:     specifically waiting in sun.misc.Unsafe.park() (presumably via LockSupport).

Dump OS Thread/Stack OS的線程運行狀態

Iuput(top):

top -Hp jvm_pid

Output:

PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND      
 2868 zhaomeng  20   0 4334856 166220   6720 S  0.0  4.8   0:00.00 java         
 2869 zhaomeng  20   0 4334856 166220   6720 S  0.0  4.8   0:00.67 java         
 2870 zhaomeng  20   0 4334856 166220   6720 S  0.0  4.8   0:01.37 java         
 2871 zhaomeng  20   0 4334856 166220   6720 S  0.0  4.8   0:01.36 java         
 2872 zhaomeng  20   0 4334856 166220   6720 S  0.0  4.8   0:01.35 java         
 2873 zhaomeng  20   0 4334856 166220   6720 S  0.0  4.8   0:01.38 java         
 2874 zhaomeng  20   0 4334856 166220   6720 S  0.0  4.8   0:03.85 java         
 2875 zhaomeng  20   0 4334856 166220   6720 S  0.0  4.8   0:00.10 java         
 2876 zhaomeng  20   0 4334856 166220   6720 S  0.0  4.8   0:00.00 java         
 2877 zhaomeng  20   0 4334856 166220   6720 S  0.0  4.8   0:00.00 java         
 2878 zhaomeng  20   0 4334856 166220   6720 S  0.0  4.8   0:09.96 java         
 2879 zhaomeng  20   0 4334856 166220   6720 S  0.0  4.8   0:09.20 java         
 2880 zhaomeng  20   0 4334856 166220   6720 S  0.0  4.8   0:03.71 java         
 2881 zhaomeng  20   0 4334856 166220   6720 S  0.0  4.8   0:00.00 java         
 2882 zhaomeng  20   0 4334856 166220   6720 S  0.0  4.8   0:29.08 java         
 2883 zhaomeng  20   0 4334856 166220   6720 S  0.0  4.8   0:00.14 java         
 2884 zhaomeng  20   0 4334856 166220   6720 S  0.0  4.8   0:00.19 java         
 2885 zhaomeng  20   0 4334856 166220   6720 S  0.0  4.8   5:29.83 java         
 2886 zhaomeng  20   0 4334856 166220   6720 S  0.0  4.8   0:00.00 java         
 2887 zhaomeng  20   0 4334856 166220   6720 S  0.0  4.8  66:06.53 java         
 2889 zhaomeng  20   0 4334856 166220   6720 S  0.0  4.8   0:00.36 java         
 2911 zhaomeng  20   0 4334856 166220   6720 S  0.0  4.8   0:00.01 java         
 2931 zhaomeng  20   0 4334856 166220   6720 S  0.0  4.8   0:00.00 java         
 3446 zhaomeng  20   0 4334856 166220   6720 S  0.0  4.8   0:00.00 java         
 3501 zhaomeng  20   0 4334856 166220   6720 S  0.0  4.8   0:00.00 java         
 3525 zhaomeng  20   0 4334856 166220   6720 S  0.0  4.8   0:00.00 java         
 3526 zhaomeng  20   0 4334856 166220   6720 S  0.0  4.8   0:00.34 java         
 3530 zhaomeng  20   0 4334856 166220   6720 S  0.0  4.8   0:33.47 java         
 3532 zhaomeng  20   0 4334856 166220   6720 S  0.0  4.8   0:12.16 java         
 3533 zhaomeng  20   0 4334856 166220   6720 S  0.0  4.8  22:27.11 java         
11120 zhaomeng  20   0 4334856 166220   6720 S  0.0  4.8   0:00.00 java

or input(ps):

ps -mp 31861 -o THREAD,tid,time | sort -rn

 

Dump Thread/Stack Analysis

  • 注意thread/stack的命名,尤爲是線程池的名字,切忌使用默認名字。(本身在建立線程或者使用線程池建立線程時,必定要取一個有意義的名字,方便分析,對於Thread-1或者pool-1-thread-1這樣的名字,很難第一眼明白它是幹什麼用的)
  • jstack顯示的thread id(nid)是16進制,對應的os顯示的thread id(pid)爲10進制,換算一下就能夠對應起來
  • 經過top -Hp能夠看到每個線程的id(PID)、實時CPU使用率(%CPU)、CPU佔用總時間(TIME+)
  • 從上面jstack的輸出和top的輸出能夠看出線程2887(0xB47) "AWT-EventQueue-0" 佔用了66mins(超過70%的cpu時間),3533(0xDCD)"RfbReceiverTask"佔用了22mins(接近20%的cpu時間),其餘線程基本沒有佔用cpu. 

Attach to JVM(Ubuntu)

sudo vi /etc/sysctl.d/10-ptrace.conf 
 kernel.yama.ptrace_scope = 0
 then reboot
 
or
sudo vi /proc/sys/kernel/yama/ptrace_scope
 0
 
or
echo 0|sudo tee /proc/sys/kernel/yama/ptrace_scope

or 
echo 0 > /proc/sys/kernel/yama/ptrace_scope
相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息