Headway Software - The Structure GuysSitemap
About us
Contact us
Structure101 > Languages > Java > Bytecode Issues

Structure101 for Java parses bytecode to populate its codebase models.

This approach is very fast and robust, and generally has extremely high fidelity. 

However, there there is one (and only one) kind of dependency that gets overlooked, namely compile-time constants

The parser also calculates 2 metric values (size and complexity) from the bytecode. Here too, the values obtained are generally very accurate, though there is one known bytecode construct that can lead to slightly anomalous values.

Compile-time constants

Compile-time constants arise where the compiler chooses to save the value of a (final) primitive field rather than the compile-time reference from which the value is obtained. 

To explain, let's first consider the standard case where there is not a problem.

Class X {
   static public int MY_PRIMITIVE = 27;
}

Class Y {
   public int doSomething() {
      return X.MY_PRIMITIVE;
   }
}

If we view this class in Structure101, we would (as expected) see a dependency from the method Y.doSomething() to the field X.MY_PRIMITIVE.

However, if we insert the keyword "final" before "static" into the declaration of X.MY_PRIMITIVE, the dependency will be lost. This is because the bytecode for the method Y.doSomething() now directly contains the fixed value of 27 (there is no reference to class Y).

Minor aside
Incidentally, if you modify the value of X.MY_PRIMITIVE to 28 and recompile X without recompiling Y (though most IDEs will recompile Y for you automatically), Y.doSomething() will continue to return 27.

Metrics

As well as extracting dependencies from the bytecode, the Structure101 parser also calculates the values for 2 method-level metrics: 

  • NI (Number of bytecode Instructions) and 
  • CC (Cyclomatic Complexity - the number of paths through the method's control flow graph).

NI is used as a measure of size. Although less commonly used than size metrics like LOC (Lines of Code) and SLOC (Source Lines of Code), it is generally much more accurate and representative since it is completely style-independent.

However, there is one source construct (namely use of ".class") where the value for bytecode NI can diverge significantly from an expected value. 

Consider the following code snippet.

Class X {
   public String getClassNameOfString1() {
      return String.class.getName();
   }
   public String getClassNameOfString2() throws ClassNotFoundException {
      return Class.forName("java.lang.String").getName();
   }   
}

The NI value for getClassNameOfString1() will actually be higher than for getClassNameOfString2. This is because the generated bytecode for the former will include additional error handling code for the case where the class in question cannot be found (at runtime).

This issue also leads to higher values for CC than would be obtained from a pure source analysis. In all other cases, the CC values correlate very closely to source-based measures.




©Headway Software 1999-2008Legal