【发布时间】:2023-04-07 13:47:01
【问题描述】:
我一直在阅读(例如here 和here),-XX:+UseSerialGC 垃圾收集器仅使用单线程进行垃圾收集。但不清楚这个“单线程”是main线程还是不同的单GC线程。
所以,我使用和不使用-XX:+UseSerialGC 进行了线程转储,在我看来,当使用此选项时,GC 由main 线程执行,因为我没有看到任何 GC 线程(如"GC task thread#0 (ParallelGC)")当我使用-XX:+UseSerialGC时。
请有JVM和GC方面经验和知识的人确认或更正我的理解。
没有-XX:+UseSerialGC:
2018-03-15 17:52:36
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.121-b13 mixed mode):
"Service Thread" #9 daemon prio=9 os_prio=0 tid=0x000000001d88d800 nid=0x1e64 runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"C1 CompilerThread2" #8 daemon prio=9 os_prio=2 tid=0x000000001d809000 nid=0x2598 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"C2 CompilerThread1" #7 daemon prio=9 os_prio=2 tid=0x000000001d806800 nid=0x30d8 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"C2 CompilerThread0" #6 daemon prio=9 os_prio=2 tid=0x000000001d801800 nid=0x1338 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"Attach Listener" #5 daemon prio=5 os_prio=2 tid=0x000000001d800800 nid=0x306c waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"Signal Dispatcher" #4 daemon prio=9 os_prio=2 tid=0x000000001c18b800 nid=0x323c runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"Finalizer" #3 daemon prio=8 os_prio=1 tid=0x000000001c16d000 nid=0x2dd0 in Object.wait() [0x000000001d7fe000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x000000076f2011d8> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:143)
- locked <0x000000076f2011d8> (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=2 tid=0x000000001c12b800 nid=0x28a8 in Object.wait() [0x000000001d61f000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x000000076f208178> (a java.lang.ref.Reference$Lock)
at java.lang.Object.wait(Object.java:502)
at java.lang.ref.Reference.tryHandlePending(Reference.java:191)
- locked <0x000000076f208178> (a java.lang.ref.Reference$Lock)
at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)
"main" #1 prio=5 os_prio=0 tid=0x000000000223d000 nid=0x3174 runnable [0x00000000026ef000]
java.lang.Thread.State: RUNNABLE
at java.io.FileOutputStream.writeBytes(Native Method)
at java.io.FileOutputStream.write(FileOutputStream.java:326)
at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:82)
at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:140)
- locked <0x000000076f2240c0> (a java.io.BufferedOutputStream)
at java.io.PrintStream.write(PrintStream.java:482)
- locked <0x000000076f201258> (a java.io.PrintStream)
at sun.nio.cs.StreamEncoder.writeBytes(StreamEncoder.java:221)
at sun.nio.cs.StreamEncoder.implFlushBuffer(StreamEncoder.java:291)
at sun.nio.cs.StreamEncoder.flushBuffer(StreamEncoder.java:104)
- locked <0x000000076f201218> (a java.io.OutputStreamWriter)
at java.io.OutputStreamWriter.flushBuffer(OutputStreamWriter.java:185)
at java.io.PrintStream.write(PrintStream.java:527)
- locked <0x000000076f201258> (a java.io.PrintStream)
at java.io.PrintStream.print(PrintStream.java:669)
at com.learn.stackoverflow.general.memory.GCThreadCount.main(GCThreadCount.java:12)
"VM Thread" os_prio=2 tid=0x000000001c124000 nid=0x25e0 runnable
"GC task thread#0 (ParallelGC)" os_prio=0 tid=0x0000000002256000 nid=0x3198 runnable
"GC task thread#1 (ParallelGC)" os_prio=0 tid=0x0000000002257800 nid=0x1ed4 runnable
"GC task thread#2 (ParallelGC)" os_prio=0 tid=0x0000000002259000 nid=0x199c runnable
"GC task thread#3 (ParallelGC)" os_prio=0 tid=0x000000000225a800 nid=0x2870 runnable
"VM Periodic Task Thread" os_prio=2 tid=0x000000001d8ad800 nid=0x1fa0 waiting on condition
JNI global references: 8
With 2018-03-15 17:52:36
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.121-b13 mixed mode):
"Service Thread" #9 daemon prio=9 os_prio=0 tid=0x000000001d88d800 nid=0x1e64 runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"C1 CompilerThread2" #8 daemon prio=9 os_prio=2 tid=0x000000001d809000 nid=0x2598 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"C2 CompilerThread1" #7 daemon prio=9 os_prio=2 tid=0x000000001d806800 nid=0x30d8 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"C2 CompilerThread0" #6 daemon prio=9 os_prio=2 tid=0x000000001d801800 nid=0x1338 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"Attach Listener" #5 daemon prio=5 os_prio=2 tid=0x000000001d800800 nid=0x306c waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"Signal Dispatcher" #4 daemon prio=9 os_prio=2 tid=0x000000001c18b800 nid=0x323c runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"Finalizer" #3 daemon prio=8 os_prio=1 tid=0x000000001c16d000 nid=0x2dd0 in Object.wait() [0x000000001d7fe000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x000000076f2011d8> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:143)
- locked <0x000000076f2011d8> (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=2 tid=0x000000001c12b800 nid=0x28a8 in Object.wait() [0x000000001d61f000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x000000076f208178> (a java.lang.ref.Reference$Lock)
at java.lang.Object.wait(Object.java:502)
at java.lang.ref.Reference.tryHandlePending(Reference.java:191)
- locked <0x000000076f208178> (a java.lang.ref.Reference$Lock)
at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)
"main" #1 prio=5 os_prio=0 tid=0x000000000223d000 nid=0x3174 runnable [0x00000000026ef000]
java.lang.Thread.State: RUNNABLE
at java.io.FileOutputStream.writeBytes(Native Method)
at java.io.FileOutputStream.write(FileOutputStream.java:326)
at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:82)
at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:140)
- locked <0x000000076f2240c0> (a java.io.BufferedOutputStream)
at java.io.PrintStream.write(PrintStream.java:482)
- locked <0x000000076f201258> (a java.io.PrintStream)
at sun.nio.cs.StreamEncoder.writeBytes(StreamEncoder.java:221)
at sun.nio.cs.StreamEncoder.implFlushBuffer(StreamEncoder.java:291)
at sun.nio.cs.StreamEncoder.flushBuffer(StreamEncoder.java:104)
- locked <0x000000076f201218> (a java.io.OutputStreamWriter)
at java.io.OutputStreamWriter.flushBuffer(OutputStreamWriter.java:185)
at java.io.PrintStream.write(PrintStream.java:527)
- locked <0x000000076f201258> (a java.io.PrintStream)
at java.io.PrintStream.print(PrintStream.java:669)
at com.learn.stackoverflow.general.memory.GCThreadCount.main(GCThreadCount.java:12)
"VM Thread" os_prio=2 tid=0x000000001c124000 nid=0x25e0 runnable
"GC task thread#0 (ParallelGC)" os_prio=0 tid=0x0000000002256000 nid=0x3198 runnable
"GC task thread#1 (ParallelGC)" os_prio=0 tid=0x0000000002257800 nid=0x1ed4 runnable
"GC task thread#2 (ParallelGC)" os_prio=0 tid=0x0000000002259000 nid=0x199c runnable
"GC task thread#3 (ParallelGC)" os_prio=0 tid=0x000000000225a800 nid=0x2870 runnable
"VM Periodic Task Thread" os_prio=2 tid=0x000000001d8ad800 nid=0x1fa0 waiting on condition
JNI global references: 8
与-XX:+UseSerialGC:
2018-03-15 17:54:47
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.121-b13 mixed mode):
"Service Thread" #9 daemon prio=9 os_prio=0 tid=0x000000001351a000 nid=0x2388 runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"C1 CompilerThread2" #8 daemon prio=9 os_prio=2 tid=0x0000000013492000 nid=0x2630 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"C2 CompilerThread1" #7 daemon prio=9 os_prio=2 tid=0x0000000013490000 nid=0x3084 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"C2 CompilerThread0" #6 daemon prio=9 os_prio=2 tid=0x000000001348b000 nid=0x32cc waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"Attach Listener" #5 daemon prio=5 os_prio=2 tid=0x0000000013489800 nid=0x3334 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"Signal Dispatcher" #4 daemon prio=9 os_prio=2 tid=0x0000000013488000 nid=0xcc0 runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"Finalizer" #3 daemon prio=8 os_prio=1 tid=0x0000000013469800 nid=0x3144 in Object.wait() [0x000000001380f000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x00000006c5a60d18> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:143)
- locked <0x00000006c5a60d18> (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=2 tid=0x0000000013422000 nid=0xf20 in Object.wait() [0x000000000259e000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x00000006c5a60ed0> (a java.lang.ref.Reference$Lock)
at java.lang.Object.wait(Object.java:502)
at java.lang.ref.Reference.tryHandlePending(Reference.java:191)
- locked <0x00000006c5a60ed0> (a java.lang.ref.Reference$Lock)
at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)
"main" #1 prio=5 os_prio=0 tid=0x00000000022cd000 nid=0x332c runnable [0x000000000274f000]
java.lang.Thread.State: RUNNABLE
at java.io.FileOutputStream.writeBytes(Native Method)
at java.io.FileOutputStream.write(FileOutputStream.java:326)
at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:82)
at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:140)
- locked <0x00000006c5a6e000> (a java.io.BufferedOutputStream)
at java.io.PrintStream.write(PrintStream.java:482)
- locked <0x00000006c5a60f20> (a java.io.PrintStream)
at sun.nio.cs.StreamEncoder.writeBytes(StreamEncoder.java:221)
at sun.nio.cs.StreamEncoder.implFlushBuffer(StreamEncoder.java:291)
at sun.nio.cs.StreamEncoder.flushBuffer(StreamEncoder.java:104)
- locked <0x00000006c5a60ee0> (a java.io.OutputStreamWriter)
at java.io.OutputStreamWriter.flushBuffer(OutputStreamWriter.java:185)
at java.io.PrintStream.write(PrintStream.java:527)
- locked <0x00000006c5a60f20> (a java.io.PrintStream)
at java.io.PrintStream.print(PrintStream.java:669)
at com.learn.stackoverflow.general.memory.GCThreadCount.main(GCThreadCount.java:12)
"VM Thread" os_prio=2 tid=0x0000000013419000 nid=0x13e8 runnable
"VM Periodic Task Thread" os_prio=2 tid=0x0000000014311000 nid=0x3364 waiting on condition
JNI global references: 8
【问题讨论】:
-
串行 GC 应该在本地 VM 线程上运行 - 而不是在任何 Java 线程上。
-
@AlexandreDupriez 感谢您的回复。能否请您详细说明。并行 GC 怎么样,对他们来说也是原生线程?
-
在Java Performance Companion,第 2 页,第 1 章中有一个线索:[...] 对于 HotSpot 垃圾收集器,几乎所有多线程 GC 操作都被处理通过内部 Java VM (JVM) 线程。一个主要的例外是 G1 垃圾收集器,其中一些后台 GC 工作可以由应用程序线程承担。
标签: java multithreading memory memory-management garbage-collection