Return unreachable code java

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

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?

8 Answers 8

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.

Читайте также:  Message from user python

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"); >> 
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.

But why wouldn’t the Java compiler eliminate the if(true) at compile time, and then identify the error when it analyzes reachable code?

Hey Uri, you can replace «if(true)» with «boolean x=true; if(x)». It’s not the compiler’s job to eliminate it, because you can, for example, put a breakpoint and change the value of x during execution

+1 The java compiler does not generate bytecode for blocks that do not get executed. Code is still generated if an expression evaluates to false at runtime. The only time bytecode is not produced is when the expression evaluates to false at compile time. At least that’s my understanding of how it works.

The Java Language specification specifically allows constant if expressions that evaluate to true or false as a means to turn code on or off, such as debug or diagnostic code, with the «flip of a switch». The expressions if(true) and if(DEBUGS) fall under this category. So neither Eclipse, nor any other Java compiler is allowed to treat them as an error. More than that, it specifically requires such constant guarded code be removed if it evaluates to false .

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

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:

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:

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

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:

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.

Источник

Resolving Java unreachable statement

The java unreachable statement is a compilation error thrown when the compiler detects a code that was not executed as part of the program. When you reach this state, it means that your program would not be executed anymore, and hence this piece of code is unnecessary and should be removed.

There are a couple of reasons that might result to this issue. Let’s discuss some of the possible causes and how to solve this:

Return Statement

Function execution ends when a return statement is called. Any statement within the function that comes after the return statement will not be executed. Thus, writing your code after this return statement results in an unreachable java statement.
Example:

Main.java:16: error: unreachable statement System.out.println("I will not be printed"); ^ 1 error 

In the above example, we have a print statement after the return statement. Using the return statement, we tell the control to go back to the caller explicitly; hence, any code after this will be considered a dead code as it will never be executed.

To solve this error, double-check the flow of your code and make sure the return statement is always the last line of code in a function.
Example:

The java unreachable statement I will not be printed

Infinite loop

An infinite loop is an endless loop. Its code keeps reiterating the loop location hence any code written after the loop will never be executed.
Example:

Main.java:10: error: unreachable statement System.out.print("I'm outside the infinite loop"); ^ 1 error

The infinite loop code executes the loop forever. This may consume the CPU, preventing other programs from being executed. As programmers, we block or sleep the loop by adding the break statement to let other applications run. Any code after the break statement will never be executed. To solve this, make sure no code is written after sleeping or blocking the infinite loop.

Any statement after continue

The continue statement enforces the execution of a loop in a code. Any statement after the continue statement will not be executed because the execution jumps to the top of the loop to continue with the execution of the previous code.
Example:

Removing the print system outside the function will make the obsolete code execute.

public class Main < public static void main(String[] args) < for (int j = 0; j < 5; j++) < System.out.println(j); continue; >System.out.println("Java unreachable statement"); > >
0 1 2 3 4 Java unreachable statement

Any statement after break

Break statements are used in terminating a loop. Any code after the break statement means the code will not be compiled since the program’s running was terminated by the break. This will result in the java unreachable statement.

Источник

How to Fix Unreachable Statement Errors in Java

How to Fix Unreachable Statement Errors in Java

Introduction to Statements and Compile-time Errors in Java

Statements are foundational language constructs that have an effect on the execution of a program. Statements are similar to sentences in natural languages. In Java, there are three main types of statements, namely expression statements, declaration statements, and control-flow statements [1].

As a compiled programming language, Java has an inbuilt mechanism for preventing many source code errors from winding up in executable programs and surfacing in production environments [2]. One such error, related to statements, is the unreachable statement error.

What Causes the Unreachable Statement Error?

By performing semantic data flow analysis, the Java compiler checks that every statement is reachable and makes sure that there exists an execution path from the beginning of a constructor, method, instance initializer, or static initializer that contains the statement, to the statement itself. If it finds a statement for which there is no such path, the compiler raises the unreachable statement error [3].

Unreachable Statement Error Examples

After a branching control-flow statement

The break , continue , and return branching statements allow the flow of execution to jump to a different part of the program. The break statement allows breaking out of a loop, the continue statement skips the current iteration of a loop, and the return statement exits a method and returns the execution flow to where the method was invoked [4]. Any statement that follows immediately after a branching statement is, by default, unreachable.

After break

When the code in Fig. 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. 1(b).

package rollbar; public class UnreachableStatementBreak < public static void main(String. args) < int[] arrayOfInts = ; int searchFor = 12; for (int integer : arrayOfInts) < if (integer == searchFor) < break; System.out.println("Found " + searchFor); >> > >
UnreachableStatementBreak.java:12: error: unreachable statement System.out.println("Found " + searchFor); ^
package rollbar; public class UnreachableStatementBreak < public static void main(String. args) < int[] arrayOfInts = ; int searchFor = 12; boolean found = false; for (int integer : arrayOfInts) < if (integer == searchFor) < found = true; break; >> if (found) < System.out.println("Found " + searchFor); >> >

Rollbar in action

Источник

Оцените статью