JVM(Thread/Stack)

JVM Thread/Stack Memory Size

-Xss1024K

 

JVM Thread/Stack Object states

(6 states)

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)

 

JVM Thread/Stack Number

(JVM 8, at least 15 threads)

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继续执行。

  • 返回值(Returen Value)
  • 局部变量表(Local Variables)
    • 局部变量表的大小在编译期就被确定。基元类型数据以及引用和返回地址(returnAddress)占用一个局部变量大小,long/double需要两个。

Java代码:

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

对应的局部变量表:

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

局部变量表说明:

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): 

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

 

转载于:https://my.oschina.net/igooglezm/blog/757587

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值