-
Notifications
You must be signed in to change notification settings - Fork 1.1k
CharacterRangeTable
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.
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
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.
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.
void example(int a, int b) { if (a == 1 && b == 1) nop(); }
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
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.
void example(int a, int b) { if (a == 1 || b == 1) nop(); }
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
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.
void example(int a, int b) { nop(a == 1 ? 2 : 3); }
0: iload_1 1: iconst_1 2: if_icmpne 9 5: iconst_2 6: goto 10 9: iconst_3 10: invokestatic #2 13: return
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.
Ranges with flag CRT_BLOCK (0x0002) could be used to filter synthetic compiler constructs.
void example() { try { nop(); } finally { nop(); } }
0: invokestatic #2 3: invokestatic #2 6: goto 15 9: astore_1 10: invokestatic #2 13: aload_1 14: athrow 15: return
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.