A very simple for-loop that I used as a dummy to keep my machine busy blocked all processes of my JVM. The stalling persisted even in the most simple constellation.
Here is an example of two for-loops (the first blocking, the second not), the only difference being the type of the 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:
UPDATE & Clarification:
It is because of the the optimizing compiler (probably trying to unroll the loop). It runs on a separate thread and that is why you see 200% CPU utilization. If you create a method out of the first loop and run it twice the second time it works as expected.
Try running your JVM like this:
java -Xint Main
That options disables the HotSpot compiler. In my case the timer thread prints on every second with no pauses.
If you run with java -XX:+PrintCompilation Main you will see that the compiler prints "made not entrant" 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
Swap the loops and it prints "made not entrant" between the 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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With