一个非常简单的 for 循环,我用作虚拟机让我的机器忙于阻塞我的 JVM 的所有进程。即使在最简单的星座中,这种停滞仍然存在。
这是两个 for 循环的示例(第一个阻塞,第二个不阻塞),唯一的区别是迭代器“i”的类型,即 int 与 long:
public class Main {
public static void main(String[] args) {
Timer timer = new Timer();
timer.schedule(new MyTimerHandler(), new Date(), 1000);
float b = 1;
// after a few seconds this loop uses 200% CPU and blocks the timer
for (int i=0; i<2000000000; i++) {
b += i/3.141592;
}
System.out.println("Result: " + b);
b = 1;
// this version uses 100% CPU throughout the entire loop and doesn't block the timer
for (long i=0; i<2000000000L; i++) {
b += i/3.141592;
}
System.out.println("Result: " + b);
timer.cancel();
}
}
// helps to show whether the JVM is stalled or not
class MyTimerHandler extends TimerTask {
@Override
public void run() {
System.out.println("timestamp=" + new Date().toString());
}
}
我们在两台不同的机器/jvm上重现了这个问题:
- Arch Linux 3.7.7-1-ARCH ... x86_64 GNU/Linux java 版本“1.7.0_09”,Java(TM) SE Runtime Environment (build 1.7.0_09-b05)
- OSX 10.8.2 ... x86_64 java 版本“1.7.0_07”,Java(TM) SE 运行时环境(内部版本 1.7.0_07-b10)
更新和澄清:
- 问题是,为什么以及究竟发生了什么,而不是“解决”给定的示例,即为什么第一个 for 循环表现得如此怪异,使用 2 倍以上的 CPU 并阻塞了 JVM 的所有线程。
- 示例代码终止并给出正确的结果。
- 计时器仅用于演示,有或没有它都会出现问题。
- int 的限制远高于 2,000,000,000。
- 到目前为止,该问题影响了所有经过测试的 JVM。
- JProfiler 和其他调试工具在第一个 for 循环期间也会中断/停止。