Pages

03 May 2012

Dead Code Elimination in Java 1.6

"Dead code" is part of source code that compiler infers that its result is not used and does not affect output of program. Obvious dead code inferences can be difficult to evaluate for compiler, since it requires longer time for detailed code analysis. Thus, it might be impossible to decide on whether a part of code is dead or not. Compilers avoid from detailed analysis for sake of precise and faster throughput.

int unusedVariables() {
  int x = 5 * 5; // unused variable = dead code = dead variable
                 // compiler warning occurs in JDK 1.6.0.30
  return 5 * 5;  
}

The definition is mentioning about a part of source code, but exactly how many lines of source code, or how many expressions should be evaluated in compile time to detect dead code. Eliminating dead code problem challenge becomes more complex while considering multiple lines of code evaluation.

int unusedVariables() {
  int x1, x2 = 0;
  x1 = x2;
  x2 = x1; // both x1 and x2 is dead and doesn't affect the output of method
           // but JDK 1.6.0.30 compiler fails to find dead code and no warning exists
  return 5 * 5; 
}

"Unreachable code" is a part of source code that there is no way to execute. For example: remaining code after return statement in a method or code after break or continue statements in same scope of a loop is a common example for unreachable code.

void simpleFlowControl(int x) {
  while(x > 0) {
    if (x == 10) {
      break;
      x--; // unreachable code
    }
    else {
      continue;
      x++; // unreachable code
    }
  }
  
  return;
  x++; // unreachable code
}

The above example is obviously clear to detect unreachable code but after making code a bit more complex, JDK 1.60.30 fails to determine unreachable code. Below, line 1 and line 2 are both unreachable because in any flow control(if or while) will allow them to be executed; but on compile time both of them has different compile time result.

void flowControl(int x) {
  while(true) {
    if (true) {
      // ...
    }
    else {
      System.out.println("dead code"); // line 1 - compiler warning(dead code) 
    }
  }

  System.out.println("unreachable code"); // line 2 - compiler error(unreachable code)
}

Do not depend on compiler for source optimization; but if compiler shows a sign about a problem in source: takes it serious and try to remove it, if possible.