Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I detect dead code after always-throwing methods?

Tags:

java

dead-code

consider the following code:

@Test 
public void testDeadCode() {
    letsThrow();
    System.out.println("will never be reached");
}

private final void letsThrow() {
    throw new RuntimeException("guess you didnt see this one coming");
}

To me it seems absolutely impossible that the println() would ever be executed - as the call to letsThrow() will always throw an exception.

Thus I am

a) surprised that the compiler can't tell me "this is dead code"

b) wondering if there are some compiler flags (or eclipse settings) that would result in telling me: you got dead code there.

like image 745
GhostCat Avatar asked Jun 08 '16 14:06

GhostCat


People also ask

How do you find the dead code?

The quickest way to find dead code is to use a good IDE. Delete unused code and unneeded files. In the case of an unnecessary class, Inline Class or Collapse Hierarchy can be applied if a subclass or superclass is used. To remove unneeded parameters, use Remove Parameter.

Which tool can be used to identify dead unused code?

UCDetector (Unnecessary Code Detector) is a eclipse PlugIn tool to find unnecessary (dead) public java code. For example public classes, methods or fields which have no references.

What type of analysis is detecting dead code?

Dead code analysis can be performed using live-variable analysis, a form of static-code analysis and data-flow analysis. This is in contrast to unreachable code analysis which is based on control-flow analysis.

What causes dead code?

Dead code is the part of your application that can never be executed. Common causes include: Programming errors in conditional branches. Code that will never be reached because the input data will never cause a specific branch to be executed.


1 Answers

Dead code compile-time errors are defined by the compiler and not the IDE. While it is true the code will never get executed, it doesn't violate any of the rules for unreachable statements from the Oracle Docs.

From Unreachable Statements

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.

The rules specifically for this case are related to whether or not the blocks you've created are reachable. (iff = if and only if)

An empty block that is not a switch block can complete normally iff it is reachable.

A non-empty block that is not a switch block can complete normally iff the last statement in it can complete normally.

The first statement in a non-empty block that is not a switch block is reachable iff the block is reachable.

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

The letsThrow method meets the criteria for a working block of code and technically completes normally. It throws an exception, but it completes. Whether or not it throws a guaranteed exception is not taken into account in determining whether that block of code in its actual use, just whether or not it can be reached. In most cases, dead code will only be found when it involves try/catch/returns, which are the bulk of the rules.

Consider the following, even more concise version:

@Test 
public void testDeadCode() {
    System.exit(0);
    System.out.println("will never be reached");
}

There's no real counter for this aside from diligent use of coverage tools, but the bright side in your example is you'll see guaranteed exceptions every time you run the code.

like image 115
Compass Avatar answered Sep 20 '22 12:09

Compass