Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unreachable code error vs. dead code warning in Java under Eclipse?

Does anyone know why:

public void foo() {     System.out.println("Hello");     return;     System.out.println("World!"); } 

Would be reported as an "unreachable error" under Eclipse, but

public void foo() {     System.out.println("Hello");     if(true) return;     System.out.println("World!"); } 

Only triggers a "Dead code" warning?

The only explanation I can think of is that the Java compiler only flags the first, and that some extra analysis in Eclipse figures out the second. However, if that is the case, why can't the Java compiler figure out this case at compile time?

Wouldn't the Java compiler figure out at compile time that the if(true) has no effect, thus yielding bytecode that is essentially identical? At what point is the reachable code analysis applied?

I guess a more general way to think of this question is: "when is the reachable code analysis applied"? In the transformation of the second Java code fragment to the final bytecode, I am sure that at some point the "if(true)" runtime equivalent is removed, and the representations of the two programs become identical. Wouldn't the Java compiler then apply its reachable code analysis again?

like image 332
Uri Avatar asked Jan 26 '10 17:01

Uri


People also ask

What is the difference between dead code and unreachable code?

unreachable code is something that would never be executed because there is no flow control to reach the code. A dead code is something that gets (or might get) executed, but its results are never used.

What does unreachable code mean in Eclipse?

means that the code at line 24 will never be reached. Here is an example of unreachable code: public void doSomething() { if (true) { return; } // All code below here is considered unreachable code doSomething() }

How do I fix unreachable statement error in Java?

1(a) is compiled, line 12 raises an unreachable statement error because the break statement exits the for loop and the successive statement cannot be executed. To address this issue, the control flow needs to be restructured and the unreachable statement removed, or moved outside the enclosing block, as shown in Fig.

What is unreachable code error in Java?

Unreachable code error occurs when the code can't be compiled due to a variety of reasons, some of which include: infinite loop, return statement before the unreachable line of code.


2 Answers

The first does not compile (you got an error), the second compiles (you just got a warning). That's the difference.

As to why Eclipse detects dead code, well, that's just the convenience of an integrated development tool with a built-in compiler which can be finetuned more as opposed to JDK to detect this kind of code.

Update: the JDK actually eliminates dead code.

public class Test {     public void foo() {         System.out.println("foo");         if(true)return;         System.out.println("foo");     }     public void bar() {         System.out.println("bar");         if(false)return;         System.out.println("bar");     } } 

javap -c says:

 public class Test extends java.lang.Object{ public Test();   Code:    0:   aload_0    1:   invokespecial   #1; //Method java/lang/Object."":()V    4:   return  public void foo();   Code:    0:   getstatic       #2; //Field java/lang/System.out:Ljava/io/PrintStream;    3:   ldc             #3; //String foo    5:   invokevirtual   #4; //Method java/io/PrintStream.println:(Ljava/lang/StrV    8:   return  public void bar();   Code:    0:   getstatic       #2; //Field java/lang/System.out:Ljava/io/PrintStream;    3:   ldc             #5; //String bar    5:   invokevirtual   #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V    8:   getstatic       #2; //Field java/lang/System.out:Ljava/io/PrintStream;    11:  ldc             #5; //String bar    13:  invokevirtual   #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V    16:  return  } 

As to why it (Sun) doesn't give a warning about that, I have no idea :) At least the JDK compiler has actually DCE (Dead Code Elimination) builtin.

like image 172
BalusC Avatar answered Oct 07 '22 23:10

BalusC


Unreachable code is an error according to the Java Language Spec.

To quote from the JLS:

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.

What that means, is that the if block is not taken into account, since if you go through one of the paths of the if statement, you could reach final print statement. If you changed your code to be:

public void foo() {     System.out.println("Hello");     if (true)         return;     else         return;     System.out.println("World!"); } 

then suddenly it wouldn't compile anymore, since there is no path through the if statement that would allow the last line to be reached.

That is, a Java compliant compiler is not allowed to compile your first code fragment. To further quote the JLS:

As an example, the following statement results in a compile-time error:

while (false) { x=3; } 

because the statement x=3; is not reachable; but the superficially similar case:

if (false) { x=3; } 

does not result in a compile-time error. An optimizing compiler may realize that the statement x=3; will never be executed and may choose to omit the code for that statement from the generated class file, but the statement x=3; is not regarded as "unreachable" in the technical sense specified here.

The second warning that Eclipse gives, about dead code, is a warning generated by the compiler, that is not "unreachable", according to the JLS, but in practice is. This is an additional lint style check that Eclipse provides. This is entirely optional, and, by using the Eclipse configuration, can be disabled, or turned into a compiler error instead of a warning.

This second block is a "code smell", if (false) blocks are normally put in to disable code for debugging purposes, having it left behind is typically accidental, and hence the warning.

In fact, Eclipse does even more advanced tests to determine the possible values for an if statement to determine whether or not it is possible to take both paths. For example, Eclipse would also complain about dead code in the following method:

public void foo() {     System.out.println("Hello");     boolean bool = Random.nextBoolean();     if (bool)         return;     if (bool || Random.nextBoolean())       System.out.println("World!"); } 

It will generate an unreachable code for the second if statement, since it can reason that bool must only be false at this point in the code. In such a short code fragment it is obvious that the two if statements are testing the same thing, however if there are 10-15 code lines in the middle it might not be so obvious anymore.

So in summary, the difference between the two: one is forbidden by the JLS, and one is not, but is detected by Eclipse as a service to the programmer.

like image 36
Paul Wagland Avatar answered Oct 08 '22 00:10

Paul Wagland