Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JAVA : Why does the following infinite loop terminate without any error / exception [duplicate]

I was messing around with stuff in my eclipse when, to my surprise, I found that this piece of code when run gets terminated without any error / exception

public class Test {
    public static void main(String[] args) {
        for(int i = 2; i > 0; i++){
            int c = 0;
        }
    }
}

while his piece of code keeps on executing

public class Test {
    public static void main(String[] args) {
        for(int i = 2; i > 0; i++){
            int c = 0;
            System.out.println(c);
        }
    }
}

Even though both ought to be infinite loops running for ever. Is there something I'm missing as to why the first code snippet is terminated?

like image 945
Ray Avatar asked Feb 08 '17 07:02

Ray


2 Answers

First of all, both snippets are not infinite loops, since i will become negative once it passes Integer.MAX_VALUE. They just take a long time to run. The first snippet takes much less time to run, since it doesn't have to print anything, and it's possible the compiler is smart enough to just optimize the code and eliminate the loop, since it does nothing.

Testing your first snippet, adding System.out.println (System.currentTimeMillis ()); before and after the loop, I got :

1486539220248
1486539221124

i.e. it ran in less than 1 second.

Changing the loop slightly :

System.out.println (System.currentTimeMillis ());
for(int i = 2; i > 0; i++){
    int c = 0;
    if (i==Integer.MAX_VALUE)
        System.out.println (i);
}
System.out.println (System.currentTimeMillis ());

I got

1486539319309
2147483647
1486539319344

As you can see, it takes i less than 1 second to increment from 0 to Integer.MAX_VALUE, and then overflow, at which point the loop terminates.

The more prints you add to the loop, the more time it will take to terminate. For example :

System.out.println (System.currentTimeMillis ());
for(int i = 2; i > 0; i++){
    int c = 0;
    if (i % 100000000 == 0)
        System.out.println (i);
}
System.out.println (System.currentTimeMillis ());

Output :

1486539560318
100000000
200000000
300000000
400000000
500000000
600000000
700000000
800000000
900000000
1000000000
1100000000
1200000000
1300000000
1400000000
1500000000
1600000000
1700000000
1800000000
1900000000
2000000000
2100000000
1486539563232

Now it took 3 seconds.

like image 104
Eran Avatar answered Oct 09 '22 00:10

Eran


The point is: this loop doesn't have any visible side effect.

Thus one could assume that the compiler is optimizing away the complete loop. On the other hand, javac isn't exactly famous for doing a lot of optimizations. Thus: lets see what happens:

javap -c Test

...

public static void main(java.lang.String[]);

   0: iconst_2      
   1: istore_1      
   2: iload_1       
   3: ifle          14
   6: iconst_0      
   7: istore_2      
   8: iinc          1, 1
  11: goto          2
  14: return        

Obviously: the loop is still there. So the real thing is: your loop stops due to int overflow at some point; and the first version of your program just reaches that point much quicker (out.println() is a very expensive operation; compared to pure adding of numbers)

like image 43
GhostCat Avatar answered Oct 09 '22 02:10

GhostCat