我写了一个睡眠一段时间的Java程序:
package com.mycompany.app;
import java.lang.System;
import java.util.concurrent.TimeUnit;
public class Main {
public static void main(String[] args) {
System.out.println("the current process's pid is " + ProcessHandle.current().pid());
try {
TimeUnit.SECONDS.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Hello World!"); // Prints the string to the console.
}
}
我运行程序:
$ java -cp target com.mycompany.app.Main
the current process's pid is 10172
我检查Ubuntu创建的进程来运行它:
$ pstree -pau -l -G -s 10172
systemd,1 splash
└─lxterminal,3194,t
└─bash,12150
└─java,10172 -cp target com.mycompany.app.Main
├─{java},10173
├─{java},10174
├─{java},10175
├─{java},10176
├─{java},10177
├─{java},10178
├─{java},10179
├─{java},10180
├─{java},10181
├─{java},10182
├─{java},10183
├─{java},10184
├─{java},10185
├─{java},10186
├─{java},10187
├─{java},10188
├─{java},10189
└─{java},10190
{java}
的线程(即轻量级进程)是为什么创建的?所有这些线程都属于JVM。
运行jstack <pid>
以获取线程列表。
"main" #1 prio=5 os_prio=0 cpu=150.00ms elapsed=8.04s tid=0x00007f9f90011000 nid=0x107 waiting on condition [0x00007f9f99f9f000]
java.lang.Thread.State: TIMED_WAITING (sleeping)
at java.lang.Thread.sleep([email protected]/Native Method)
at java.lang.Thread.sleep([email protected]/Thread.java:339)
at java.util.concurrent.TimeUnit.sleep([email protected]/TimeUnit.java:446)
at com.mycompany.app.Main.main(Main.java:10)
"Reference Handler" #2 daemon prio=10 os_prio=0 cpu=0.00ms elapsed=7.95s tid=0x00007f9f901f9000 nid=0x10e waiting on condition [0x00007f9f6c10f000]
java.lang.Thread.State: RUNNABLE
at java.lang.ref.Reference.waitForReferencePendingList([email protected]/Native Method)
at java.lang.ref.Reference.processPendingReferences([email protected]/Reference.java:241)
at java.lang.ref.Reference$ReferenceHandler.run([email protected]/Reference.java:213)
"Finalizer" #3 daemon prio=8 os_prio=0 cpu=0.00ms elapsed=7.95s tid=0x00007f9f901fd800 nid=0x10f in Object.wait() [0x00007f9f65fef000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait([email protected]/Native Method)
- waiting on <0x0000000712108f80> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove([email protected]/ReferenceQueue.java:155)
- waiting to re-lock in wait() <0x0000000712108f80> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove([email protected]/ReferenceQueue.java:176)
at java.lang.ref.Finalizer$FinalizerThread.run([email protected]/Finalizer.java:170)
"Signal Dispatcher" #4 daemon prio=9 os_prio=0 cpu=0.00ms elapsed=7.93s tid=0x00007f9f90210000 nid=0x110 runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"C2 CompilerThread0" #5 daemon prio=9 os_prio=0 cpu=40.00ms elapsed=7.93s tid=0x00007f9f90212000 nid=0x111 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
No compile task
"C1 CompilerThread0" #7 daemon prio=9 os_prio=0 cpu=40.00ms elapsed=7.93s tid=0x00007f9f90214000 nid=0x112 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
No compile task
"Sweeper thread" #8 daemon prio=9 os_prio=0 cpu=10.00ms elapsed=7.93s tid=0x00007f9f90216000 nid=0x113 runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"Service Thread" #9 daemon prio=9 os_prio=0 cpu=0.00ms elapsed=7.90s tid=0x00007f9f902d3800 nid=0x114 runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"Common-Cleaner" #10 daemon prio=8 os_prio=0 cpu=0.00ms elapsed=7.89s tid=0x00007f9f902df800 nid=0x116 in Object.wait() [0x00007f9f656ef000]
java.lang.Thread.State: TIMED_WAITING (on object monitor)
at java.lang.Object.wait([email protected]/Native Method)
- waiting on <0x0000000712002df0> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove([email protected]/ReferenceQueue.java:155)
- waiting to re-lock in wait() <0x0000000712002df0> (a java.lang.ref.ReferenceQueue$Lock)
at jdk.internal.ref.CleanerImpl.run([email protected]/CleanerImpl.java:148)
at java.lang.Thread.run([email protected]/Thread.java:834)
at jdk.internal.misc.InnocuousThread.run([email protected]/InnocuousThread.java:134)
"Attach Listener" #11 daemon prio=9 os_prio=0 cpu=0.00ms elapsed=0.21s tid=0x00007f9f44001000 nid=0x126 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"VM Thread" os_prio=0 cpu=0.00ms elapsed=7.95s tid=0x00007f9f901f1000 nid=0x10d runnable
"GC Thread#0" os_prio=0 cpu=0.00ms elapsed=8.01s tid=0x00007f9f90038800 nid=0x108 runnable
"G1 Main Marker" os_prio=0 cpu=0.00ms elapsed=8.00s tid=0x00007f9f90097800 nid=0x109 runnable
"G1 Conc#0" os_prio=0 cpu=0.00ms elapsed=8.00s tid=0x00007f9f90099800 nid=0x10a runnable
"G1 Refine#0" os_prio=0 cpu=0.00ms elapsed=8.00s tid=0x00007f9f9018d000 nid=0x10b runnable
"G1 Young RemSet Sampling" os_prio=0 cpu=0.00ms elapsed=8.00s tid=0x00007f9f9018f000 nid=0x10c runnable
"VM Periodic Task Thread" os_prio=0 cpu=0.00ms elapsed=7.90s tid=0x00007f9f902d6000 nid=0x115 waiting on condition
这里nid
是操作系统中线程的十六进制ID - 你可以将它与pstree
的输出相匹配。
main
的第一个线程是执行代码的线程。Reference Handler
线程负责将垃圾收集器发现的Weak,Soft和Phantom引用添加到其注册的ReferenceQueues中。Finalizer
线程运行finalize
方法准备完成的对象。Signal Dispatcher
等待特定的OS信号并处理它们。特别是,它在SIGQUIT
上进行线程转储,并在SIGTERM
,SIGINT
和SIGHUP
上启动VM关闭过程。CompilerThreads
执行字节码的JIT编译。Sweeper thread
清理过时的编译方法。Service Thread
运行几个后台JVM任务:检测低内存条件,清除StringTable和SymbolTable,发送延迟的JVMTI事件和GC通知等等。Common-Cleaner
运行java.lang.ref.Cleaner
实例的清洁行动。Attach Listener
线程支持动态附加机制。它侦听传入的动态连接连接并执行VM命令。例如,它由jstack
,jmap
和jcmd
实用程序使用。VM Thread
运行需要safepoint的内部VM操作。这种操作的例子是去优化,类重定义,偏向锁撤销,线程转储,堆检查等。G1
线程涉及垃圾收集。VM Periodic Task Thread
用于模拟定时器中断。