參考《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方法進行操做系統層面的系統調用。下面的圖能比較清楚的說明問題。