参考《Java内存泄漏分析系列》html
属性含义java
"http-nio-9090-exec-2" 线程名称 prio 优先级 os_prio 系统优先级 tid 虚拟机中的Java线程id nid 线程在操做系统中的id [0x00007f5822648000] 线程栈起始内存地址
2018-06-15 01:12:34 Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.144-b01 mixed mode):
"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)
JVM 内部运行线程介绍linux
VM Thread,负责建立其它全部线程,并经过自轮询VMOperationQueue
,按照优先级执行VM_Operation
,例如ThreadDump、CMS_Initial_Mark。apache
"VM Thread" os_prio=0 tid=0x00007f59283c6000 nid=0xac91 runnable
Attach Listener,负责处理JVM外部的命令,如jstack
,在第一次执行JVM命令时启动。windows
"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接收到的命令,第一次分发时启动。tomcat
"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,用于启动服务的线程。app
"Service Thread" #20 daemon prio=9 os_prio=0 tid=0x00007f5928431800 nid=0xaca4 runnable [0x0000000000000000] java.lang.Thread.State: RUNNABLE
CompilerThread,实时编译装卸class,可能会形成CPU抖动。jvm
"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线程处理。socket
"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 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; } }
如下摘录这篇博客的部分描述,对于回过头来理清概念比较重要。
VM是加载并执行字节码的机器,这个处理不对应具体硬件,它彻底由软件来实现。虚拟机并非直接跑在宿主的cpu上,中间还隔着宿主的操做系统。
虚拟机的职责是:翻译字节码,把它翻译成一系列的动做(内存操做)和系统调用(好比输入输出)。
举个例子:当在java里请求与某台远程机器创建socket链接时,java虚拟机自己是不能完成这一工做的(协议栈是在操做系统内实现的),因此它须要系统调用。
要明白这个,还须要知道JRE和JVM的关系。JRE是JVM的环境,一个应用程序就是一个JVM实例。
一个机器上通常同时只有一个JRE环境,可是能够同时有多个JVM实例。
不一样的操做系统和CPU架构有不一样的JRE。JRE包含了最基本的类库,固然包括和操做系统打交道的Native库,好比windows下的dll文件,linux下的so文件。
JVM实例解析字节码的成JVM中的指令集,再经过Native方法进行操做系统层面的系统调用。下面的图能比较清楚的说明问题。