OpenJDK JVM是否并行化字节码?

时间:2013-10-03 16:06:02

标签: java parallel-processing openjdk

我使用单线程Java代码实现了一种算法。当我使用JIT编译启动程序时,它会使我机器上的所有8个内核饱和。当我使用-Xint JVM选项运行相同的程序来禁用JIT编译时,它会按预期在单个核心上运行。

这是我的Java版本信息:

java version "1.7.0_25"
OpenJDK Runtime Environment (IcedTea 2.3.10) (7u25-2.3.10-1ubuntu0.12.10.2)
OpenJDK 64-Bit Server VM (build 23.7-b01, mixed mode)

为什么看起来我的代码会被并行化,哪里可以找到有关HotSpot何时可以并行化代码的更多信息?

3 个答案:

答案 0 :(得分:7)

Java不会自动并行化代码,我猜你所看到的核心饱和度是JIT编译你的代码。让你的测试程序输入更大,以便它运行更长时间(可能是2-3分钟),看看它是否会在一段时间后关闭。

答案 1 :(得分:2)

它不会直接自动对您的代码进行并行化,但它会使用更多的机器资源来使代码运行得更快。它是基于运行时数据进行分析,编译,垃圾收集和不断重新编译。只要有可能,这些操作将在其他CPU上完成。

它可能决定使用相同的参数调用一个方法,以便完整地为该参数创建结果,或者如果它们从未被采用,它可能会优化给定方法中的相当多的if语句,从而产生原始if你有不同的参数。它不希望这些操作减慢/阻止你的程序,所以它在不同的线程上执行它们。

我猜你是否跑得足够长,虽然你会看到它回到填充单个cpu。

答案 2 :(得分:1)

上面给出的答案基本上是正确的。我只是回答完成图片。显然,JVM不会自动并行化用户代码,并且它拥有自己的线程。这些线程的数量不尽相同,但通常我们有以下线程。线程堆栈的快照是在热点(OpenJDK)JVM的实时阶段开始时获取的。我们在这里可以看到11个线程,它们可以轻松占据octacore或quadcore机器的所有核心。线程名称也解释了它们的用途。

Full thread dump OpenJDK 64-Bit Server VM (25.71-b00-debug mixed mode):

"Service Thread" #9 daemon prio=9 os_prio=0 tid=0x00007ffff0160800 nid=0x2f91 runnable [0x0000000000000000]

"C1 CompilerThread3" #8 daemon prio=9 os_prio=0 tid=0x00007ffff0158800 nid=0x2f90 waiting on condition [0x0000000000000000]

"C2 CompilerThread2" #7 daemon prio=9 os_prio=0 tid=0x00007ffff0156000 nid=0x2f8f waiting on condition [0x0000000000000000]

"C2 CompilerThread1" #6 daemon prio=9 os_prio=0 tid=0x00007ffff0153000 nid=0x2f8e waiting on condition [0x0000000000000000]

"C2 CompilerThread0" #5 daemon prio=9 os_prio=0 tid=0x00007ffff0150800 nid=0x2f8d waiting on condition [0x0000000000000000]

"Signal Dispatcher" #4 daemon prio=9 os_prio=0 tid=0x00007ffff014e800 nid=0x2f8c runnable [0x0000000000000000]

"Finalizer" #3 daemon prio=8 os_prio=0 tid=0x00007ffff0103800 nid=0x2f8b in Object.wait() [0x00007ffff412f000]

"Reference Handler" #2 daemon prio=10 os_prio=0 tid=0x00007ffff00fa000 nid=0x2f8a in Object.wait() [0x00007ffff4230000]

"main" #1 prio=5 os_prio=0 tid=0x00007ffff000d000 nid=0x2f86 runnable [0x00007ffff7fca000]

"VM Thread" os_prio=0 tid=0x00007ffff00ef800 nid=0x2f89 runnable 

"VM Periodic Task Thread" os_prio=0 tid=0x00007ffff015f000 nid=0x2f92 waiting on condition 

同样,跟随线程堆栈的快照显示垃圾收集器正在运行。在GC调用之后执行此快照。由于我正在运行GC的并行实现,因此GC只有8个线程(我猜GC线程等于内核数量,因为我在octacore机器上进行测试)。

Full thread dump OpenJDK 64-Bit Server VM (25.71-b00-debug mixed mode):

"Service Thread" #9 daemon prio=9 os_prio=0 tid=0x00007ffff017e800 nid=0xaa1 runnable  (no locks) [0x0000000000000000]

"C1 CompilerThread3" #8 daemon prio=9 os_prio=0 tid=0x00007ffff016e800 nid=0xaa0 waiting on condition  (no locks) [0x0000000000000000]

"C2 CompilerThread2" #7 daemon prio=9 os_prio=0 tid=0x00007ffff016b800 nid=0xa9f waiting on condition  (no locks) [0x0000000000000000]

"C2 CompilerThread1" #6 daemon prio=9 os_prio=0 tid=0x00007ffff0169800 nid=0xa9e waiting on condition  (no locks) [0x0000000000000000]

"C2 CompilerThread0" #5 daemon prio=9 os_prio=0 tid=0x00007ffff0166000 nid=0xa9d waiting on condition  (no locks) [0x0000000000000000]

"Signal Dispatcher" #4 daemon prio=9 os_prio=0 tid=0x00007ffff0164800 nid=0xa9c runnable  (no locks) [0x0000000000000000]

"Finalizer" #3 daemon prio=8 os_prio=0 tid=0x00007ffff0119000 nid=0xa9b in Object.wait()  (no locks) [0x00007fffba33d000]

"Reference Handler" #2 daemon prio=10 os_prio=0 tid=0x00007ffff0110000 nid=0xa9a in Object.wait()  (no locks) [0x00007fffba43e000]

"main" #1 prio=5 os_prio=0 tid=0x00007ffff000d000 nid=0xa8b runnable  (no locks) [0x00007ffff7fc9000]

"VM Thread" os_prio=0 tid=0x00007ffff0105000 nid=0xa99 runnable  (no locks) 

"GC task thread#0 (ParallelGC)" os_prio=0 tid=0x00007ffff0026800 nid=0xa91 runnable  (no locks) 

"GC task thread#1 (ParallelGC)" os_prio=0 tid=0x00007ffff0028800 nid=0xa92 runnable  (no locks) 

"GC task thread#2 (ParallelGC)" os_prio=0 tid=0x00007ffff002a800 nid=0xa93 runnable  (no locks) 

"GC task thread#3 (ParallelGC)" os_prio=0 tid=0x00007ffff002c800 nid=0xa94 runnable  (no locks) 

"GC task thread#4 (ParallelGC)" os_prio=0 tid=0x00007ffff002e800 nid=0xa95 runnable  (no locks) 

"GC task thread#5 (ParallelGC)" os_prio=0 tid=0x00007ffff0030800 nid=0xa96 runnable  (no locks) 

"GC task thread#6 (ParallelGC)" os_prio=0 tid=0x00007ffff0032800 nid=0xa97 runnable  (no locks) 

"GC task thread#7 (ParallelGC)" os_prio=0 tid=0x00007ffff0034800 nid=0xa98 runnable  (no locks) 

"VM Periodic Task Thread" os_prio=0 tid=0x00007ffff017f800 nid=0xaa2 waiting on condition  (no locks) 

结论

由于线程数在运行时变化,并且许多线程在运行中被生成和终止,因此无论运行多长时间,您几乎都不会看到java程序正在使用的单个核心。

上面的输出是使用GDB和openJDK的内部调试API生成的。如果有人有兴趣了解这些主题及其目的的更多信息,请参阅:Thread Management in openJDK