views:

514

answers:

8

Given the following code sample:

public class WeirdStuff {

 public static int doSomething() {
  while(true);
 }

 public static void main(String[] args) {
  doSomething();
 }
}

This is a valid Java program, although the method doSomething() should return an int but never does. If you run it, it will end in an infinite loop. If you put the argument of the while loop in a separate variable (e.g. boolean bool = true) the compiler will tell you to return an int in this method.

So my question is: is this somewhere in the Java specification and are there situation where this behavior might be useful?

+6  A: 

If you are asking if infinite loops can be useful, the answer is yes. There are plenty of situations where you want something running forever, though the loop will usually be terminated at some point.

As to your question: "Can java recognized when a loop will be infinite?" The answer is that it is impossible for a computer to have an algorithm to determine if a program will run forever or not. Read about: Halting Problem

Reading a bit more, your question is also asking why the doSomething() function does not complain that it is not returning an int.

Interestingly the following source does NOT compile.

public class test {
  public static int doSomething() {                
   //while(true);
   boolean test=true;
   while(test){


   }
  }  
  public static void main(String[] args) {               
   doSomething();    
  }
}

This indicates to me that, as the wiki page on the halting problem suggests, it is impossible for there to be an algorithm to determine if every problem will terminate, but this does not mean someone hasn't added the simple case:

while(true);

to the java spec. My example above is a little more complicated, so Java can't have it remembered as an infinite loop. Truely, this is a weird edge case, but it's there just to make things compile. Maybe someone will try other combinations.

EDIT: not an issue with unreachable code.

import java.util.*;

public class test {
  public static int doSomething() {                
   //while(true);
   while(true){
    System.out.println("Hello"); 
   }
  }  
  public static void main(String[] args) {               
   doSomething();    
  }
}

The above works, so the while(true); isn't being ignored by the compiler as unreachable, otherwise it would throw a compile time error!

windfinder
Your answer is misleading. It's impossible for a computer program to recognize whether an arbitrary program halts or not, but it's definitely not impossible to check whether "specific programs" halt or not. Definitely, the fact that `while (true);` without a `break` or `goto` statement is an infinite loop can be checked by the compiler.
Mehrdad Afshari
Yes, I corrected this above.
windfinder
boolean test=true; while(test){ } is not necessarily an infinite loop. Another thread could change the value of 'test'.
Skip Head
+1  A: 

Yes, you can see these 'infinite' loops in some threads, for example server threads that listen on a certain port for incoming messages.

Andreas_D
A: 

After rereading the question....

Java understands while(true); can never actually complete, it does not trace the following code completely.

boolean moo = true;
while (moo);

Is this useful? Doubtful.

Chris Kannon
And what is that "actually doing"?
Stephen C
This is not necessarily an infinite loop. Another thread could set 'moo' to false.
Skip Head
+7  A: 

Java specification defines a concept called Unreachable statements. You are not allowed to have an unreachable statement in your code (it's a compile time error). A while(true); statement makes the following statements unreachable by definition. You are not even allowed to have a return statement after the while(true); statement in Java. Note that while Halting problem is undecidable in generic case, the definition of Unreachable Statement is more strict than just halting. It's deciding very specific cases where a program definitely does not halt. The compiler is theoretically not able to detect all infinite loops and unreachable statements but it has to detect specific cases defined in the spec.

Mehrdad Afshari
But, it does compile. Also: while(true){ //code } compiles too, without returning that int!
windfinder
`while(true)` is not unreachable (clearly!). Any statement that would follow `while(true)` is unreachable.
Pavel Minaev
Pavel: Right. That's what I meant, of course.
Mehrdad Afshari
windfinder: `while(true);` compiles fine but `while (true); return 0;` will not.
Mehrdad Afshari
Fact that it compiles without returning is strange!
fastcodejava
@fastcodejava: Actually, if the statement after the loop was not considered unreachable (say, if it was `bool x = true; while(x);`), the compiler would consider exiting the loop a possible "code path" and would require you to write a `return` statement there. Otherwise, it would not compile **without** `return`.
Mehrdad Afshari
+1  A: 

So my question is: is this somewhere in the Java specification

The program is legal Java according to the specification. The JLS (and Java compiler) recognize that the method cannot return, and therefore no return statement is required. Indeed, if you added a return statement after the loop, the Java compiler would give you a compilation error because the return statement would be unreachable code.

and are there situation where this behavior might be useful?

I don't think so, except possibly in obscure unit tests.

I occasionally write methods that will never return (normally), but putting the current thread into an uninterruptible infinite busy-loop rarely makes any sense.

Stephen C
A: 

You might be implementing a general interface such that, even though the method may exit with a meaningful return value, your particular implementation is a useful infinite loop (for example, a network server) which never has a situation where it should exit, i.e. trigger whatever action returning a value means.

Also, regarding code like boolean x = true; while (x);, this will compile given a final modifier on x. I don't know offhand but I would imagine this is Java's choice of reasonable straightforward constant expression analysis (which needs to be defined straightforwardly since, due to this rejection of programs dependent on it, it is part of the language definition).

Kevin Reid
+3  A: 

I'll just quote the Java Language Specification, as it's rather clear on this:

This section is devoted to a precise explanation of the word "reachable." The idea is that there must be some possible execution path from the beginning of the constructor, method, instance initializer or static initializer that contains the statement to the statement itself. The analysis takes into account the structure of statements. Except for the special treatment of while, do, and for statements whose condition expression has the constant value true, the values of expressions are not taken into account in the flow analysis.

...

A while statement can complete normally iff at least one of the following is true:

  • The while statement is reachable and the condition expression is not a constant expression with value true.
  • There is a reachable break statement that exits the while statement.

...

Every other statement S in a nonempty block that is not a switch block is reachable iff the statement preceding S can complete normally.

And then apply the above definitions to this:

If a method is declared to have a return type, then every return statement (§14.17) in its body must have an Expression. A compile-time error occurs if the body of the method can complete normally (§14.1).

In other words, a method with a return type must return only by using a return statement that provides a value return; it is not allowed to "drop off the end of its body."

Note that it is possible for a method to have a declared return type and yet contain no return statements. Here is one example:

class DizzyDean {
  int pitch() { throw new RuntimeException("90 mph?!"); }
}
Pavel Minaev
JLS to the rescue! \o/
Bombe
A: 

Some notes about unreachable statements:

In java2 specs the description of 'unreachable statement' could be found. Especially interesting the following sentence:

Except for the special treatment of while, do, and for statements whose condition expression has the constant value true, the values of expressions are not taken into account in the flow analysis.

So, it is not obviously possible to exit from while (true); infinite loop. However, there were two more options: change cached values or hack directly into class file or JVM operating memory space.

Dair T'arg