深入分析JVM中线程的创建和运行原理 || JIT(future)
https://blog.csdn.net/J080624/article/details/86020746
在JVM中除了应用线程,还有其他的一些线程用于支持JVM的运行,这些线程可以被划分为以下几类:
-
VM Thread:负责JVM在安全点内的各种操作,这些操作(诸如自动内存管理、取消偏向锁、线程dump、线程挂起等等)在执行过程中需要JVM处于这样一个状态——堆的内容不会被改变,这种状态在JVM里叫做安全点(safe-point)。
-
Periodic task thread:这个线程负责响应定时触发的事件(例如:中断),用来执行一些定时操作。
-
GC thread:这些线程负责JVM里的垃圾收集活动;
-
Compiler threads:这些线程负责在运行时将字节码编译为本地代码;
-
Singal dispatcher thread:这些线程负责响应外部发给当前JVM进程的信号,并通过调用JVM内的其他线程。
我们再用jstack命令做一次线程dump,就可以得到如下内容:
jstack内容一般在最后:
"Service Thread" #8 daemon prio=9 os_prio=0 tid=0x00007f486018f800 nid=0x3110 runnable [0x0000000000000000] java.lang.Thread.State: RUNNABLE "C1 CompilerThread2" #7 daemon prio=9 os_prio=0 tid=0x00007f4860184800 nid=0x310f waiting on condition [0x0000000000000000] java.lang.Thread.State: RUNNABLE "C2 CompilerThread1" #6 daemon prio=9 os_prio=0 tid=0x00007f4860182800 nid=0x310e waiting on condition [0x0000000000000000] java.lang.Thread.State: RUNNABLE "C2 CompilerThread0" #5 daemon prio=9 os_prio=0 tid=0x00007f486017f800 nid=0x310d waiting on condition [0x0000000000000000] java.lang.Thread.State: RUNNABLE "Signal Dispatcher" #4 daemon prio=9 os_prio=0 tid=0x00007f486017e000 nid=0x310c runnable [0x0000000000000000] java.lang.Thread.State: RUNNABLE "Finalizer" #3 daemon prio=8 os_prio=0 tid=0x00007f486014b000 nid=0x310b in Object.wait() [0x00007f4850bfa000] java.lang.Thread.State: WAITING (on object monitor) at java.lang.Object.wait(Native Method) at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:143) - locked <0x00000000e0e0c390> (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" #2 daemon prio=10 os_prio=0 tid=0x00007f4860146800 nid=0x310a in Object.wait() [0x00007f4850cfb000] java.lang.Thread.State: WAITING (on object monitor) at java.lang.Object.wait(Native Method) at java.lang.Object.wait(Object.java:502) at java.lang.ref.Reference.tryHandlePending(Reference.java:191) - locked <0x00000000e0e0c5c0> (a java.lang.ref.Reference$Lock) at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153) "VM Thread" os_prio=0 tid=0x00007f486013f000 nid=0x3109 runnable "GC task thread#0 (ParallelGC)" os_prio=0 tid=0x00007f486001e800 nid=0x3105 runnable "GC task thread#1 (ParallelGC)" os_prio=0 tid=0x00007f4860020800 nid=0x3106 runnable "GC task thread#2 (ParallelGC)" os_prio=0 tid=0x00007f4860022800 nid=0x3107 runnable "GC task thread#3 (ParallelGC)" os_prio=0 tid=0x00007f4860024000 nid=0x3108 runnable "VM Periodic Task Thread" os_prio=0 tid=0x00007f4860194800 nid=0x3111 waiting on condition JNI global references: 1925
可以看到,有2个c2 compiler thread,jdk默认即是2个线程
C2 CompilerThread线程项目启动初期cpu使用率那么高,它在干什么呢?
Java程序在启动的时候所有代码的执行都处于解释执行模式,只有在运行了一段时间后,根据代码方法执行的次数,或代码里循环的执行次数等达到一定的阈值才会编译成机器码,编译成机器码后执行效率会得到大幅提升,而随着执行时间进一步拉长,JVM的各种更高级的编译优化手段就会逐渐加上,例如if条件的执行状况,逃逸分析等。这里的C2 CompilerThread线程干的就是编译优化的活。
编译方式有三种:1)Client模式;2)Server模式;3)Tiered模式。我们服务默认是Server模式。
Server模式是采用c2高级编译的,会比较耗时且要运行一段时间才会触发编译。 Server模式的优点是编译后程序效率较高;
Client模式比较轻量也比较快触发(比Server模式触发快),编译优化后程序效率不如Server模式;
Tiered模式是Client模式和Server模式的折中,一开始会启用Client模式,可以在启动后更快的让部分代码先进入编译优化阶段,之后会启动Server模式,达到程序效率最大优化的目的。
Oracle JDK 7里的HotSpot VM已经开始有比较好的Tiered编译(tiered compilation)支持,可以设置参数-XX:+TieredCompilation来启动Tiered模式,java 8默认就是Tiered模式。
详见:https://www.cnblogs.com/silyvin/p/10226774.html
-=============================-
HotSpot中内置了两个即时编译器,分别称为 Client Compiler和 Server Compiler ,或者简称为 C1 编译器和 C2 编译器。目前的 HotSpot 编译器默认的是解释器和其中一个即时编译器配合的方式工作,具体是哪一个编译器,取决于虚拟机运行的模式,HotSpot 虚拟机会根据自身版本与计算机的硬件性能自动选择运行模式,用户也可以使用 -client 和 -server 参数强制指定虚拟机运行在 Client 模式或者 Server 模式。这种配合使用的方式称为“混合模式”(Mixed Mode)
- 被多次调用的方法
- 被多次执行的循环体
http://www.cnblogs.com/linghu-java/p/8589843.html
附:
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.151-b12 mixed mode): "RMI TCP Connection(5)-192.168.0.139" #17 daemon prio=9 os_prio=31 tid=0x00007fba7c830800 nid=0x5c03 runnable [0x000070000f740000] java.lang.Thread.State: RUNNABLE at java.net.SocketInputStream.socketRead0(Native Method) at java.net.SocketInputStream.socketRead(SocketInputStream.java:116) at java.net.SocketInputStream.read(SocketInputStream.java:171) at java.net.SocketInputStream.read(SocketInputStream.java:141) at java.io.BufferedInputStream.fill(BufferedInputStream.java:246) at java.io.BufferedInputStream.read(BufferedInputStream.java:265) - locked <0x000000076f590708> (a java.io.BufferedInputStream) at java.io.FilterInputStream.read(FilterInputStream.java:83) at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:550) at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:826) at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:683) at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler$$Lambda$3/745402377.run(Unknown Source) at java.security.AccessController.doPrivileged(Native Method) at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:682) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at java.lang.Thread.run(Thread.java:748) "RMI TCP Connection(2)-192.168.0.139" #16 daemon prio=9 os_prio=31 tid=0x00007fba7e0b0000 nid=0xa403 in Object.wait() [0x000070000f63c000] java.lang.Thread.State: TIMED_WAITING (on object monitor) at java.lang.Object.wait(Native Method) - waiting on <0x000000076f580878> (a com.sun.jmx.remote.internal.ArrayNotificationBuffer) at com.sun.jmx.remote.internal.ArrayNotificationBuffer.fetchNotifications(ArrayNotificationBuffer.java:449) - locked <0x000000076f580878> (a com.sun.jmx.remote.internal.ArrayNotificationBuffer) at com.sun.jmx.remote.internal.ArrayNotificationBuffer$ShareBuffer.fetchNotifications(ArrayNotificationBuffer.java:227) at com.sun.jmx.remote.internal.ServerNotifForwarder.fetchNotifs(ServerNotifForwarder.java:274) at javax.management.remote.rmi.RMIConnectionImpl$4.run(RMIConnectionImpl.java:1270) at javax.management.remote.rmi.RMIConnectionImpl$4.run(RMIConnectionImpl.java:1268) at javax.management.remote.rmi.RMIConnectionImpl.fetchNotifications(RMIConnectionImpl.java:1274) at sun.reflect.GeneratedMethodAccessor62.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:357) at sun.rmi.transport.Transport$1.run(Transport.java:200) at sun.rmi.transport.Transport$1.run(Transport.java:197) at java.security.AccessController.doPrivileged(Native Method) at sun.rmi.transport.Transport.serviceCall(Transport.java:196) at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:568) at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:826) at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:683) at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler$$Lambda$3/745402377.run(Unknown Source) at java.security.AccessController.doPrivileged(Native Method) at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:682) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at java.lang.Thread.run(Thread.java:748) "JMX server connection timeout 15" #15 daemon prio=9 os_prio=31 tid=0x00007fba80014800 nid=0xa503 in Object.wait() [0x000070000f53b000] java.lang.Thread.State: TIMED_WAITING (on object monitor) at java.lang.Object.wait(Native Method) - waiting on <0x000000076f5887f8> (a [I) at com.sun.jmx.remote.internal.ServerCommunicatorAdmin$Timeout.run(ServerCommunicatorAdmin.java:168) - locked <0x000000076f5887f8> (a [I) at java.lang.Thread.run(Thread.java:748) "RMI Scheduler(0)" #14 daemon prio=9 os_prio=31 tid=0x00007fba7c805800 nid=0xa603 waiting on condition [0x000070000f438000] java.lang.Thread.State: TIMED_WAITING (parking) at sun.misc.Unsafe.park(Native Method) - parking to wait for <0x000000076f598188> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject) at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215) at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2078) at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1093) at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:809) 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 java.lang.Thread.run(Thread.java:748) "RMI TCP Accept-0" #12 daemon prio=9 os_prio=31 tid=0x00007fba7d906000 nid=0xa803 runnable [0x000070000f232000] java.lang.Thread.State: RUNNABLE at java.net.PlainSocketImpl.socketAccept(Native Method) at java.net.AbstractPlainSocketImpl.accept(AbstractPlainSocketImpl.java:409) at java.net.ServerSocket.implAccept(ServerSocket.java:545) at java.net.ServerSocket.accept(ServerSocket.java:513) at sun.management.jmxremote.LocalRMIServerSocketFactory$1.accept(LocalRMIServerSocketFactory.java:52) at sun.rmi.transport.tcp.TCPTransport$AcceptLoop.executeAcceptLoop(TCPTransport.java:400) at sun.rmi.transport.tcp.TCPTransport$AcceptLoop.run(TCPTransport.java:372) at java.lang.Thread.run(Thread.java:748) "Attach Listener" #10 daemon prio=9 os_prio=31 tid=0x00007fba7d865800 nid=0xa903 waiting on condition [0x0000000000000000] java.lang.Thread.State: RUNNABLE "Service Thread" #9 daemon prio=9 os_prio=31 tid=0x00007fba7d803000 nid=0x3903 runnable [0x0000000000000000] java.lang.Thread.State: RUNNABLE "C1 CompilerThread3" #8 daemon prio=9 os_prio=31 tid=0x00007fba7e002000 nid=0x3803 waiting on condition [0x0000000000000000] java.lang.Thread.State: RUNNABLE "C2 CompilerThread2" #7 daemon prio=9 os_prio=31 tid=0x00007fba80000000 nid=0x3703 waiting on condition [0x0000000000000000] java.lang.Thread.State: RUNNABLE "C2 CompilerThread1" #6 daemon prio=9 os_prio=31 tid=0x00007fba7d82d800 nid=0x3e03 waiting on condition [0x0000000000000000] java.lang.Thread.State: RUNNABLE "C2 CompilerThread0" #5 daemon prio=9 os_prio=31 tid=0x00007fba7c020000 nid=0x3f03 waiting on condition [0x0000000000000000] java.lang.Thread.State: RUNNABLE "Signal Dispatcher" #4 daemon prio=9 os_prio=31 tid=0x00007fba7c01e800 nid=0x3403 runnable [0x0000000000000000] java.lang.Thread.State: RUNNABLE "Finalizer" #3 daemon prio=8 os_prio=31 tid=0x00007fba7f022000 nid=0x4903 in Object.wait() [0x000070000e917000] java.lang.Thread.State: WAITING (on object monitor) at java.lang.Object.wait(Native Method) - waiting on <0x000000076f5a0600> (a java.lang.ref.ReferenceQueue$Lock) at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:143) - locked <0x000000076f5a0600> (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" #2 daemon prio=10 os_prio=31 tid=0x00007fba7c01d800 nid=0x4b03 in Object.wait() [0x000070000e814000] java.lang.Thread.State: WAITING (on object monitor) at java.lang.Object.wait(Native Method) - waiting on <0x000000076f5983e8> (a java.lang.ref.Reference$Lock) at java.lang.Object.wait(Object.java:502) at java.lang.ref.Reference.tryHandlePending(Reference.java:191) - locked <0x000000076f5983e8> (a java.lang.ref.Reference$Lock) at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153) "main" #1 prio=5 os_prio=31 tid=0x00007fba7f000000 nid=0x2303 runnable [0x000070000ddf6000] java.lang.Thread.State: RUNNABLE at GcExample.main(GcExample.java:9) "VM Thread" os_prio=31 tid=0x00007fba7c01b000 nid=0x2f03 runnable "GC task thread#0 (ParallelGC)" os_prio=31 tid=0x00007fba7c007000 nid=0x2007 runnable "GC task thread#1 (ParallelGC)" os_prio=31 tid=0x00007fba7d804800 nid=0x2a03 runnable "GC task thread#2 (ParallelGC)" os_prio=31 tid=0x00007fba7c007800 nid=0x5303 runnable "GC task thread#3 (ParallelGC)" os_prio=31 tid=0x00007fba7f800000 nid=0x2c03 runnable "GC task thread#4 (ParallelGC)" os_prio=31 tid=0x00007fba7d805000 nid=0x5103 runnable "GC task thread#5 (ParallelGC)" os_prio=31 tid=0x00007fba7c013800 nid=0x5003 runnable "GC task thread#6 (ParallelGC)" os_prio=31 tid=0x00007fba7f001000 nid=0x4e03 runnable "GC task thread#7 (ParallelGC)" os_prio=31 tid=0x00007fba7c014000 nid=0x4c03 runnable "VM Periodic Task Thread" os_prio=31 tid=0x00007fba7d858800 nid=0x3a03 waiting on condition JNI global references: 295
OK,从上面这个dump文件中,可以找到Periodic Task Thread、GC Thread、VM Thread、Compiler Thread的身影了。