JVM线程
dump文件结构
属性含义
"http-nio-9090-exec-2" 线程名称
prio 优先级
os_prio 系统优先级
tid 虚拟机中的Java线程id
nid 线程在操作系统中的id
[0x00007f5822648000] 线程栈起始内存地址
Identifier & Version
2018-06-15 01:12:34
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.144-b01 mixed mode):
Application Threads
"http-nio-9090-exec-2" #38 daemon prio=5 os_prio=0 tid=0x00007f592b133800 nid=0xacc6 waiting on condition [0x00007f5822648000]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x000000076b27c218> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442)
at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:103)
at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:31)
at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1074)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:748)
VM Threads
VM Thread,负责创建其它所有线程,并通过自轮询VMOperationQueue
,按照优先级执行VM_Operation
,例如ThreadDump、CMS_Initial_Mark。
"VM Thread" os_prio=0 tid=0x00007f59283c6000 nid=0xac91 runnable
Attach Listener,负责处理JVM外部的命令,如jstack
,在第一次执行JVM命令时启动。
"Attach Listener" #54 daemon prio=9 os_prio=0 tid=0x00007f589c001000 nid=0xae90 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Signal Dispatcher,负责分发Attach Listener接收到的命令,第一次分发时启动。
"Signal Dispatcher" #4 daemon prio=9 os_prio=0 tid=0x00007f5928405000 nid=0xac94 runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
DestroyJavaVM,负责卸载JVM。
"DestroyJavaVM" #52 prio=5 os_prio=0 tid=0x00007f5928008800 nid=0xac78 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Service Thread,用于启动服务的线程。
"Service Thread" #20 daemon prio=9 os_prio=0 tid=0x00007f5928431800 nid=0xaca4 runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
CompilerThread,实时编译装卸class,可能会造成CPU抖动。
"C1 CompilerThread14" #19 daemon prio=9 os_prio=0 tid=0x00007f5928426000 nid=0xaca3 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Finalizer,负责在垃圾回收前调用对象的finalize()
方法。JVM将失去引用的对象包装成Finalizer对象(Reference的实现),放入ReferenceQueue,由Finalizer线程处理。
"Finalizer" #3 daemon prio=8 os_prio=0 tid=0x00007f59283d2000 nid=0xac93 in Object.wait() [0x00007f58ddedd000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x000000068782bac0> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:143)
- locked <0x000000068782bac0> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:164)
at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:209)
Reference Handler,优先级最高,负责处理引用对象本身的垃圾回收问题。
"Reference Handler" #2 daemon prio=10 os_prio=0 tid=0x00007f59283cd800 nid=0xac92 in Object.wait() [0x00007f58ddfde000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x000000068782bab0> (a java.lang.ref.Reference$Lock)
at java.lang.Object.wait(Object.java:502)
at java.lang.ref.Reference.tryHandlePending(Reference.java:191)
- locked <0x000000068782bab0> (a java.lang.ref.Reference$Lock)
at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)
GC Thread
GC task thread,GC线程,创建后会一直复用,逻辑CPU不大于8时,线程数量为CPU数,否则为8 + ( ncpus - 8 ) * 5/8
,线程数逻辑。
"GC task thread#0 (ParallelGC)" os_prio=0 tid=0x00007f592801e000 nid=0xac79 runnable
unsigned int Abstract_VM_Version::calc_parallel_worker_threads() {
return nof_parallel_worker_threads(5, 8, 8);
}
unsigned int Abstract_VM_Version::nof_parallel_worker_threads(
unsigned int num,
unsigned int den,
unsigned int switch_pt) {
if (FLAG_IS_DEFAULT(ParallelGCThreads)) {
assert(ParallelGCThreads == 0, "Default ParallelGCThreads is not 0");
// For very large machines, there are diminishing returns
// for large numbers of worker threads. Instead of
// hogging the whole system, use a fraction of the workers for every
// processor after the first 8. For example, on a 72 cpu machine
// and a chosen fraction of 5/8
// use 8 + (72 - 8) * (5/8) == 48 worker threads.
unsigned int ncpus = (unsigned int) os::initial_active_processor_count();
return (ncpus <= switch_pt) ?
ncpus :
(switch_pt + ((ncpus - switch_pt) * num) / den);
} else {
return ParallelGCThreads;
}
}
[虚拟机stack全分析]
以下摘录这篇博客的部分描述,对于回过头来理清概念比较重要。
VM是加载并执行字节码的机器,这个处理不对应具体硬件,它完全由软件来实现。虚拟机并不是直接跑在宿主的cpu上,中间还隔着宿主的操作系统。
虚拟机的职责是:翻译字节码,把它翻译成一系列的动作(内存操作)和系统调用(比如输入输出)。
举个例子:当在java里请求与某台远程机器建立socket连接时,java虚拟机本身是不能完成这一工作的(协议栈是在操作系统内实现的),所以它需要系统调用。
要明白这个,还需要知道JRE和JVM的关系。JRE是JVM的环境,一个应用程序就是一个JVM实例。
一个机器上一般同时只有一个JRE环境,但是可以同时有多个JVM实例。
不同的操作系统和CPU架构有不同的JRE。JRE包含了最基本的类库,当然包括和操作系统打交道的Native库,比如windows下的dll文件,linux下的so文件。
JVM实例解析字节码的成JVM中的指令集,再通过Native方法进行操作系统层面的系统调用。下面的图能比较清楚的说明问题。