Exploring Coverage Analysis Views > Learning More About Coverage Results > Nonintuitive Results for Some Source Code
JProbe provides test case coverage results on executable source code. You may find instances, however, where JProbe appears to assign data to lines of source code that are clearly not executable, such as a comment or single brace. To understand how these results occur, you need to look to your javac compiler.
When your javac compiler compiles your source code into .class files, the class files contain executable bytecode. The compiler may also add debugging information that maps the bytecode to lines of source code in the .java file. It saves this mapping in a line table in the class file. The mapping can sometimes be surprising, and it can vary with different compilers, compiler versions, javac options (eg. -g), or even the formatting of the source code. For example, javac may attribute bytecode to the closing brace (}) of a void method even if the method has no return statement, or may attribute it to the last line of code.
JProbe uses the mappings in the line table to match the coverage results for your bytecode to the lines in your source code. JProbe cannot modify these mappings.
The following table summarizes some of the nonintuitive results that you may see in JProbe and provides an explanation of the compiler behavior that causes these results:
A class declaration or its opening brace is reported as missed rather than unexecutable. |
This happens when the compiler generates a default constructor for a class with no explicit constructor, but the constructor is not used. Most compilers generate a line table for this method that attributes the code to the class declaration itself–either the line with the class keyword or the opening brace ({). Workaround: To ignore the unused method in subsequent JProbe sessions, add a data collection filter: |
Data is assigned inconsistently to the closing braces of blocks. |
Most compilers inconsistently attribute code to the closing brace (}) of a block. In addition, sometimes the compiler generates code at the end of a block to skip subsequent blocks, such as subsequent catch blocks or the else portion of an if statement. |
Data is assigned inconsistently to the closing braces of methods. |
In bytecode, methods must always have an explicit return statement. In the Java language, however, the return statement is optional for void methods. For most compilers, if a return statement exists, the bytecode is assigned to it. Otherwise, the bytecode is assigned to the closing brace. |
A catch line with no source code is reported as missed rather than unexecutable. |
Most compilers generate code to save caught exceptions.This code is usually (but not always) attributed to the catch() clause itself rather than the block associated with it, whether or not that block is empty. Many test cases do not exercise this generated code, so JProbe reports it as missed. Workaround: To remove all data associated with catch blocks (including additional bytecode generated by the compiler), select the “Filter out catch blocks” display option. For more information, see Filtering Out Catch Block Data. |
The start or end of some synchronized blocks are unexpectedly colored as catch blocks when the JProbe “Filter out catch blocks” display option is enabled. |
The bytecode to acquire and release the monitor associated with a synchronized block is normally attributed to the start and end of the block respectively. There is also, however, an implicit exception handler (catch block) generated to release the monitor in the event of an exception. The exception handler bytecode may be attributed to either the start or end of the block. JProbe identifies the affected lines in the synchronized block as a catch block. |
Data is assigned inconsistently to one or more of the lines that make up a statement. |
When source code for a statement is split over multiple lines, the compiler may attribute the bytecode for the statement to one or more of the lines of source code. For example, consider the following two statements: for (i = 0; The compiler may attribute code to all three lines in the for statement, but only to the first line in the String concatenation. |
Uninitialized variable declarations are reported as missed rather than unexecutable. |
When creating the line table for a method, a few
compilers assume that the start of the bytecode for the method can be
attributed to the first line. If this first line is a statement with
no executable code such as an uninitialized variable declaration • Initialize variable declarations (int i = 0;) • Move the declaration below the first line of executable code |
The last line of a catch block before a finally block is reported as hit, even though the rest of the catch block may be missed. |
Some older compilers may misattribute code from a finally block to the last line of code in a preceding catch block. |