while(true); loop throws Unreachable code when isn't in a void while(true); loop throws Unreachable code when isn't in a void java java

while(true); loop throws Unreachable code when isn't in a void


The language spec has an exact definition what the compiler should treat as unreachable code, see also https://stackoverflow.com/a/20922409/14955.

In particular, it does not care about if a method completes, and it does not look inside other methods.

It won't do more than that.

However, you could get static code analysis tools like FindBugs to get a "deeper" analysis (not sure if they detect the pattern you described, though, either, and, as has been pointed out by others, the halting problem in all generality cannot be algorithmically solved anyway, so one has to draw the line at some reasonably definition of "best effort").


In general, it is not possible to determine with absolute certainly whether or not something is reachable.

Why? It is the equivalent to the Halting Problem.

The halting problem asks:

Given a description of an arbitrary computer program, decide whether the program finishes running or continues to run forever.

This problem has been proven to be unsolvable.


Whether or not X piece of code is reachable is the same as saying whether the code before it will halt.

Because it is an unsolvable problem, the compiler (in Java or any other language) doesn't try very hard to solve it. If it happens to determine that it really is unreachable, then you get the warning. If not, it may or may not be reachable.

In Java, unreachable code is a compiler error. So in order to maintain compatibility, the language spec defines exactly "how hard" the compiler should try. (Which according to the other answers, is "don't go inside another function".)

In other languages (such as C++), the compiler may go further subject to optimizations. (Unreachable code may be detected after inlining the function and discovering that it never returns.)


Unreachable code is a compile time error that simply says 'the flow of this program doesn't make sense; something will never ever be reached'.

Obviously your tests perform how they do due to an endless loop, but why does the first fail with a compile time error?

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

  • The while statement is reachable and the condition expression is not a constant expression (§15.28) with value true.

  • There is a reachable break statement that exits the while statement.

Alright, but what about methods invocations (such as a()) - why do tests 2 and 3 successfully compile?

  • An expression statement can complete normally if it is reachable.

Since a method invocation is considered an expression, they will always be reachable so long as nothing before it blocks its path of logical execution.


To better illustrate some reasoning behind this compilation mechanism, let's take an if statement, for example.

if(false)   System.out.println("Hello!"); // Never executes

The above will be correct at compile time (though many IDE's will definitely whine!).

The Java 1.7 Specification talks about this:

The rationale for this differing treatment is to allow programmers to define "flag variables" such as:

static final boolean DEBUG = false;

and then write code such as:

if (DEBUG) { x=3; }

The idea is that it should be possible to change the value of DEBUG from false to true or from true to false and then compile the code correctly with no other changes to the program text.

Further, there is actually a backwards compatibility reason as well:

This ability to "conditionally compile" has a significant impact on, and relationship to, binary compatibility (§13). If a set of classes that use such a "flag" variable are compiled and conditional code is omitted, it does not suffice later to distribute just a new version of the class or interface that contains the definition of the flag. A change to the value of a flag is, therefore, not binary compatible with pre-existing binaries (§13.4.9). (There are other reasons for such incompatibility as well, such as the use of constants in case labels in switch statements; see §13.4.9.)


Most (per the spec), if not all, implementations of the Java compiler do not traverse into methods. When parsing your Java code itself, it sees a() as just a MethodInvocationElement, meaning 'This code calls other code. I really don't care, I'm just looking at syntax.'. Syntactically, it makes sense for subsequent code to belong after a call to a().

Keep in mind performance costs. Compilation already takes a considerable amount of time. In order to keep things quick, the Java compiler doesn't actually recurse into methods; that would take ages (the compiler would have to evaluate many, many paths of code -- in theory).


To further reiterate that it's syntactically driven is to add a return; statement directly after your loop in a(). Doesn't compile, does it? Syntactically, though, it makes sense without it.