Skip to content

CharacterRangeTable

Joachim Vandersmissen edited this page Jun 30, 2017 · 32 revisions

This page discusses a not yet available feature!

The CharacterRangeTable is a non-standard (not defined in The Java Virtual Machine Specification) optional variable-length attribute in the attributes table of a Code attribute.

Compilers

Can be produced by javac from OracleJDK 1.5 - 1.9 and IBM JDK 1.5 - 1.8 with help of non-standard undocumented option "-Xjcov", which is ignored by Eclipse Compiler.

Support of this attribute is unlikely to disappear soon:

  • OpenJDK JCov can use it for some scenarios

  • javap starting from OpenJDK 7 decodes content of this attribute

  • it receives fixes in recent versions of OpenJDK - JDK-8059453

  • JDK-8020204

Format

See com/sun/tools/classfile/CharacterRangeTable_attribute.java

CharacterRangeTable_attribute {
  u2 start_pc;
  u2 end_pc;
  u4 character_range_start;
  u4 character_range_end;
  u2 flags;
}

Each character_range encodes line and column as following:

line = character_range >> 10
column = character_range & 0x03ff

Seems that flags CRT_ASSIGNMENT (0x0004), CRT_INVOKE (0x0020) and CRT_CREATE (0x0040) are never produced.

How can be used

Condition coverage

Ranges with flags CRT_BRANCH_TRUE (0x0080) and CRT_BRANCH_FALSE (0x0100) are of particular interest, because could be used to map bytecode branches back to conditions in source code.

Logical and

Source
  void example(int a, int b) {
    if (a == 1 && b == 1)
      nop();
  }
Code
         0: iload_1
         1: iconst_1
         2: if_icmpne     13
         5: iload_2
         6: iconst_1
         7: if_icmpne     13
        10: invokestatic  #2
        13: return
CharacterRangeTable
  0,  1,    3:09,    3:15, flow-controller
  2,  4,    3:09,    3:15, branch-false
  5,  6,    3:19,    3:25, flow-target
  0,  6,    3:09,    3:25, flow-controller
  7,  9,    3:09,    3:25, branch-false
 10, 12,    4:07,    4:13, statement, flow-target
  0, 12,    3:05,    4:13, statement
  0, 13,    2:30,    5:03, block

if branch 2 was taken, then condition 3:09-3:15 (a == 1) evaluates to false,
if branch 7 was taken, then condition 3:09-3:25 (a == 1 && b == 1) evaluates to false.

Logical or

Source
  void example(int a, int b) {
    if (a == 1 || b == 1)
      nop();
  }
Code
         0: iload_1
         1: iconst_1
         2: if_icmpeq     10
         5: iload_2
         6: iconst_1
         7: if_icmpne     13
        10: invokestatic  #2
        13: return
CharacterRangeTable
  0,  1,    3:09,    3:15, flow-controller
  2,  4,    3:09,    3:15, branch-true
  5,  6,    3:19,    3:25, flow-target
  0,  6,    3:09,    3:25, flow-controller
  7,  9,    3:09,    3:25, branch-false
 10, 12,    4:07,    4:13, statement, flow-target
  0, 12,    3:05,    4:13, statement
  0, 13,    2:30,    5:03, block

if branch 2 was taken, then condition 3:09-3:15 (a == 1) evaluates to true,
if branch 7 was taken, then condition 3:09-3:25 (a == 1 || b == 1) evaluates to false.

Conditional operator

Source
  void example(int a, int b) {
    nop(a == 1 ? 2 : 3);
  }
Code
         0: iload_1
         1: iconst_1
         2: if_icmpne     9
         5: iconst_2
         6: goto          10
         9: iconst_3
        10: invokestatic  #2
        13: return
CharacterRangeTable
  0,  1,    3:09,    3:15, flow-controller
  2,  4,    3:09,    3:15, branch-false
  5,  5,    3:18,    3:19, flow-target
  9,  9,    3:22,    3:23, flow-target
  0, 12,    3:05,    3:25, statement
  0, 13,    2:30,    4:03, block

if branch 2 was taken, then condition 3:09-3:15 (a == 1) evaluates to false.

Filtering

Ranges with flag CRT_BLOCK (0x0002) could be used to filter synthetic compiler constructs.

Duplicated finally blocks

Source
  void example() {
    try {
      nop();
    } finally {
      nop();
    }
  }
Code
         0: invokestatic  #2
         3: invokestatic  #2
         6: goto          15
         9: astore_1
        10: invokestatic  #2
        13: aload_1
        14: athrow
        15: return
CharacterRangeTable
  0,  2,    4:07,    4:13, statement
  0,  2,    3:09,    5:05, block
  3,  5,    6:07,    6:13, statement
  3,  5,    5:15,    7:05, block
 10, 12,    6:07,    6:13, statement
 10, 12,    5:15,    7:05, block
  0, 14,    3:05,    7:05, statement
  0, 15,    2:18,    8:03, block

same source code corresponds to instructions 3-5 and 10-12.