Skip to content

CharacterRangeTable

Evgeny Mandrikov edited this page May 17, 2015 · 32 revisions

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".

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

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 & 0x3ff

How can be used

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.

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.

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.