Starting a process in a simple for-loop depending on the type of iterator (potential JVM bug?)
A very simple for-loop that I used as a dummy to keep my machine busy would block all my JVM processes. The collision persisted even in the simplest constellation.
Here is an example of two for-loops (the first one is blocking, the second one is not), the only difference is the type of iterator i, namely int vs. 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());
}
}
We have reproduced the problem on two different machines / jvms:
- Arch Linux 3.7.7-1-ARCH ... x86_64 GNU / Linux java version "1.7.0_09", Java (TM) SE Runtime Environment (build 1.7.0_09-b05)
- OSX 10.8.2 ... x86_64 java version "1.7.0_07", Java (TM) SE Runtime Environment (build 1.7.0_07-b10)
UPDATE and clarification:
- The question is WHY and WHAT EXACTLY is happening, not "allow" this example, but because the first for-loop behaves so strangely, using 2x more CPU and blocking all JVM threads.
- The sample code ends and gives the correct result.
- The timer is for demonstration only, problems occur with or without it.
- The int limit is over 2,000,000,000.
- The problem affects all tested JVMs so far.
- JProfiler and other debugging tools interrupted / stopped during first for-loop.
source to share
This is because of the optimizing compiler (maybe trying to unwrap the loop). It runs on a separate thread, so you see 200% CPU usage. If you create a method from the first loop and run it twice the second time, it works as expected.
Try to start the JVM like this:
java -Xint Main
These options disable the HotSpot compiler. In my case, the timer thread prints every second without pauses.
If you run with java -XX:+PrintCompilation Main
, you will see that the compiler prints "not contributed" in the middle of the first loop.
79 6 java.lang.String::lastIndexOf (52 bytes)
90 1 % test.Main::main @ 33 (141 bytes)
timestamp=Thu Feb 14 12:10:40 PST 2013
timestamp=Thu Feb 14 12:10:41 PST 2013
timestamp=Thu Feb 14 12:10:42 PST 2013
timestamp=Thu Feb 14 12:10:43 PST 2013
timestamp=Thu Feb 14 12:10:44 PST 2013
13202 1 % test.Main::main @ -2 (141 bytes) made not entrant
timestamp=Thu Feb 14 12:10:53 PST 2013
Result: 1.80143985E16
13202 2 % test.Main::main @ 85 (141 bytes)
timestamp=Thu Feb 14 12:10:54 PST 2013
timestamp=Thu Feb 14 12:10:55 PST 2013
Move the hinges and it prints "fail" between two loops.
72 6 java.lang.String::lastIndexOf (52 bytes)
85 1 % test.Main::main @ 33 (141 bytes)
timestamp=Thu Feb 14 12:12:38 PST 2013
timestamp=Thu Feb 14 12:12:39 PST 2013
timestamp=Thu Feb 14 12:12:40 PST 2013
timestamp=Thu Feb 14 12:12:41 PST 2013
15415 1 % test.Main::main @ -2 (141 bytes) made not entrant
Result: 1.80143985E16
15415 2 % test.Main::main @ 88 (141 bytes)
timestamp=Thu Feb 14 12:12:42 PST 2013
timestamp=Thu Feb 14 12:12:43 PST 2013
source to share
Using AProVE ( http://aprove.informatik.rwth-aachen.de ) I have proven that the first loop actually ends. Please check out some other possibly non-terminating code, most likely a timer (as pointed out in the comments).
source to share