CharacterRangeTable
转载:https://github.com/jacoco/jacoco/wiki/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.
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
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
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

package com.test19; public class Test05 { void example(int a, int b) { if (a == 1 && b == 1) nop(); } void nop(){}; }
生成的class文件如下:
public class com.test19.Test05 SourceFile: "Test05.java" Utf8 1533252190610Utf8 1533252242529minor version: 0 major version: 51 flags: ACC_PUBLIC, ACC_SUPER Constant pool: #1 = Methodref #4.#20 // java/lang/Object."<init>":()V #2 = Methodref #3.#21 // com/test19/Test05.nop:()V #3 = Class #22 // com/test19/Test05 #4 = Class #23 // java/lang/Object #5 = Utf8 <init> #6 = Utf8 ()V #7 = Utf8 Code #8 = Utf8 LineNumberTable #9 = Utf8 CharacterRangeTable #10 = Utf8 example #11 = Utf8 (II)V #12 = Utf8 StackMapTable #13 = Utf8 nop #14 = Utf8 SourceFile #15 = Utf8 Test05.java #16 = Utf8 SourceID #17 = Utf8 1533252190610 #18 = Utf8 CompilationID #19 = Utf8 1533252242529 #20 = NameAndType #5:#6 // "<init>":()V #21 = NameAndType #13:#6 // nop:()V #22 = Utf8 com/test19/Test05 #23 = Utf8 java/lang/Object { public com.test19.Test05(); flags: ACC_PUBLIC Code: stack=1, locals=1, args_size=1 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init> ":()V 4: return LineNumberTable: line 3: 0 CharacterRangeTable: void example(int, int); flags: Code: stack=2, locals=3, args_size=3 0: iload_1 1: iconst_1 2: if_icmpne 14 5: iload_2 6: iconst_1 7: if_icmpne 14 10: aload_0 11: invokevirtual #2 // Method nop:()V 14: return LineNumberTable: line 5: 0 line 6: 10 line 7: 14 CharacterRangeTable: 0, 1, 1407, 140d, 8 // 0, 1, 5:07, 5:13, flow-controller 2, 4, 1407, 140d, 100 // 2, 4, 5:07, 5:13, branch-false 5, 6, 1411, 1417, 10 // 5, 6, 5:17, 5:23, flow-target 0, 6, 1407, 1417, 8 // 0, 6, 5:07, 5:23, flow-controller 7, 9, 1407, 1417, 100 // 7, 9, 5:07, 5:23, branch-false 10, 13, 1804, 180a, 11 // 10, 13, 6:04, 6:10, statement, flow-target 0, 13, 1403, 180a, 1 // 0, 13, 5:03, 6:10, statement 0, 14, 101d, 1c02, 2 // 0, 14, 4:29, 7:02, block StackMapTable: number_of_entries = 1 frame_type = 14 /* same */ void nop(); flags: Code: stack=0, locals=1, args_size=1 0: return LineNumberTable: line 8: 0 CharacterRangeTable: 0, 0, 200c, 200d, 2 // 0, 0, 8:12, 8:13, 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
package com.test19; public class Test05 { void example(int a, int b) { if (a == 1 || b == 1) { nop(); } } void nop() {} }
public class com.test19.Test05 SourceFile: "Test05.java" Utf8 1533253036302Utf8 1533253190932minor version: 0 major version: 51 flags: ACC_PUBLIC, ACC_SUPER Constant pool: #1 = Methodref #4.#20 // java/lang/Object."<init>":()V #2 = Methodref #3.#21 // com/test19/Test05.nop:()V #3 = Class #22 // com/test19/Test05 #4 = Class #23 // java/lang/Object #5 = Utf8 <init> #6 = Utf8 ()V #7 = Utf8 Code #8 = Utf8 LineNumberTable #9 = Utf8 CharacterRangeTable #10 = Utf8 example #11 = Utf8 (II)V #12 = Utf8 StackMapTable #13 = Utf8 nop #14 = Utf8 SourceFile #15 = Utf8 Test05.java #16 = Utf8 SourceID #17 = Utf8 1533253036302 #18 = Utf8 CompilationID #19 = Utf8 1533253190932 #20 = NameAndType #5:#6 // "<init>":()V #21 = NameAndType #13:#6 // nop:()V #22 = Utf8 com/test19/Test05 #23 = Utf8 java/lang/Object { public com.test19.Test05(); flags: ACC_PUBLIC Code: stack=1, locals=1, args_size=1 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init> ":()V 4: return LineNumberTable: line 3: 0 CharacterRangeTable: void example(int, int); flags: Code: stack=2, locals=3, args_size=3 0: iload_1 1: iconst_1 2: if_icmpeq 10 5: iload_2 6: iconst_1 7: if_icmpne 14 10: aload_0 11: invokevirtual #2 // Method nop:()V 14: return LineNumberTable: line 5: 0 line 6: 10 line 8: 14 CharacterRangeTable: 0, 1, 1407, 140d, 8 // 0, 1, 5:07, 5:13, flow-controller 2, 4, 1407, 140d, 80 // 2, 4, 5:07, 5:13, branch-true 5, 6, 1411, 1417, 10 // 5, 6, 5:17, 5:23, flow-target 0, 6, 1407, 1417, 8 // 0, 6, 5:07, 5:23, flow-controller 7, 9, 1407, 1417, 100 // 7, 9, 5:07, 5:23, branch-false 10, 13, 1804, 180a, 1 // 10, 13, 6:04, 6:10, statement 10, 13, 1419, 1c03, 13 // 10, 13, 5:25, 7:03, statement, block, flow-target 0, 13, 1403, 1c03, 1 // 0, 13, 5:03, 7:03, statement 0, 14, 101d, 2002, 2 // 0, 14, 4:29, 8:02, block StackMapTable: number_of_entries = 2 frame_type = 10 /* same */ frame_type = 3 /* same */ void nop(); flags: Code: stack=0, locals=1, args_size=1 0: return LineNumberTable: line 9: 0 CharacterRangeTable: 0, 0, 240d, 240e, 2 // 0, 0, 9:13, 9:14, blo ck }
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

package com.test19; public class Test05 { void example(int a, int b) { nop(a == 1 ? 2 : 3); } void nop(int x) {} }
public class com.test19.Test05 SourceFile: "Test05.java" Utf8 1533253525422Utf8 1533253540376minor version: 0 major version: 51 flags: ACC_PUBLIC, ACC_SUPER Constant pool: #1 = Methodref #4.#22 // java/lang/Object."<init>":()V #2 = Methodref #3.#23 // com/test19/Test05.nop:(I)V #3 = Class #24 // com/test19/Test05 #4 = Class #25 // java/lang/Object #5 = Utf8 <init> #6 = Utf8 ()V #7 = Utf8 Code #8 = Utf8 LineNumberTable #9 = Utf8 CharacterRangeTable #10 = Utf8 example #11 = Utf8 (II)V #12 = Utf8 StackMapTable #13 = Class #24 // com/test19/Test05 #14 = Utf8 nop #15 = Utf8 (I)V #16 = Utf8 SourceFile #17 = Utf8 Test05.java #18 = Utf8 SourceID #19 = Utf8 1533253525422 #20 = Utf8 CompilationID #21 = Utf8 1533253540376 #22 = NameAndType #5:#6 // "<init>":()V #23 = NameAndType #14:#15 // nop:(I)V #24 = Utf8 com/test19/Test05 #25 = Utf8 java/lang/Object { public com.test19.Test05(); flags: ACC_PUBLIC Code: stack=1, locals=1, args_size=1 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init>":()V 4: return LineNumberTable: line 3: 0 CharacterRangeTable: void example(int, int); flags: Code: stack=3, locals=3, args_size=3 0: aload_0 1: iload_1 2: iconst_1 3: if_icmpne 10 6: iconst_2 7: goto 11 10: iconst_3 11: invokevirtual #2 // Method nop:(I)V 14: return LineNumberTable: line 5: 0 line 6: 14 CharacterRangeTable: 1, 2, 1407, 140d, 8 // 1, 2, 5:07, 5:13, flow-controller 3, 5, 1407, 140d, 100 // 3, 5, 5:07, 5:13, branch-false 6, 6, 1410, 1411, 10 // 6, 6, 5:16, 5:17, flow-target 10, 10, 1414, 1415, 10 // 10, 10, 5:20, 5:21, flow-target 0, 13, 1403, 1417, 1 // 0, 13, 5:03, 5:23, statement 0, 14, 101d, 1802, 2 // 0, 14, 4:29, 6:02, block StackMapTable: number_of_entries = 2 frame_type = 74 /* same_locals_1_stack_item */ stack = [ class com/test19/Test05 ] frame_type = 255 /* full_frame */ offset_delta = 0 locals = [ class com/test19/Test05, int, int ] stack = [ class com/test19/Test05, int ] void nop(int); flags: Code: stack=0, locals=2, args_size=2 0: return LineNumberTable: line 7: 0 CharacterRangeTable: 0, 0, 1c12, 1c13, 2 // 0, 0, 7:18, 7:19, 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

package com.test19; public class Test05 { void example() { try { nop(); } finally { nop(); } } void nop() {} }
public class com.test19.Test05 SourceFile: "Test05.java" Utf8 1533253682139Utf8 1533253727858minor version: 0 major version: 51 flags: ACC_PUBLIC, ACC_SUPER Constant pool: #1 = Methodref #4.#20 // java/lang/Object."<init>":()V #2 = Methodref #3.#21 // com/test19/Test05.nop:()V #3 = Class #22 // com/test19/Test05 #4 = Class #23 // java/lang/Object #5 = Utf8 <init> #6 = Utf8 ()V #7 = Utf8 Code #8 = Utf8 LineNumberTable #9 = Utf8 CharacterRangeTable #10 = Utf8 example #11 = Utf8 StackMapTable #12 = Class #24 // java/lang/Throwable #13 = Utf8 nop #14 = Utf8 SourceFile #15 = Utf8 Test05.java #16 = Utf8 SourceID #17 = Utf8 1533253682139 #18 = Utf8 CompilationID #19 = Utf8 1533253727858 #20 = NameAndType #5:#6 // "<init>":()V #21 = NameAndType #13:#6 // nop:()V #22 = Utf8 com/test19/Test05 #23 = Utf8 java/lang/Object #24 = Utf8 java/lang/Throwable { public com.test19.Test05(); flags: ACC_PUBLIC Code: stack=1, locals=1, args_size=1 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init>":()V 4: return LineNumberTable: line 3: 0 CharacterRangeTable: void example(); flags: Code: stack=1, locals=2, args_size=1 0: aload_0 1: invokevirtual #2 // Method nop:()V 4: aload_0 5: invokevirtual #2 // Method nop:()V 8: goto 18 11: astore_1 12: aload_0 13: invokevirtual #2 // Method nop:()V 16: aload_1 17: athrow 18: return Exception table: from to target type 0 4 11 any 11 12 11 any LineNumberTable: line 6: 0 line 8: 4 line 9: 8 line 8: 11 line 10: 18 CharacterRangeTable: 0, 3, 1804, 180a, 1 // 0, 3, 6:04, 6:10, statement 0, 3, 1407, 1c03, 2 // 0, 3, 5:07, 7:03, block 4, 7, 2004, 200a, 1 // 4, 7, 8:04, 8:10, statement 4, 7, 1c0d, 2403, 2 // 4, 7, 7:13, 9:03, block 12, 15, 2004, 200a, 1 // 12, 15, 8:04, 8:10, statement 12, 15, 1c0d, 2403, 2 // 12, 15, 7:13, 9:03, block 0, 17, 1403, 2403, 1 // 0, 17, 5:03, 9:03, statement 0, 18, 1011, 2802, 2 // 0, 18, 4:17, 10:02, block StackMapTable: number_of_entries = 2 frame_type = 75 /* same_locals_1_stack_item */ stack = [ class java/lang/Throwable ] frame_type = 6 /* same */ void nop(); flags: Code: stack=0, locals=1, args_size=1 0: return LineNumberTable: line 12: 0 CharacterRangeTable: 0, 0, 300d, 300e, 2 // 0, 0, 12:13, 12:14, block }
same source code corresponds to instructions 3-5 and 10-12.
CharacterRangeTable的更多相关文章
- Gen类的字符串操作
public void t(String d){ final String str = "b"; String s = "a"+"c"+st ...
随机推荐
- 玩转Nodejs的集群
在Nodejs中使用集群还是不容易的.Javascript的单线程属性让nodejs下的应用很难使用现代机器的多核特性.比如下面的代码实现了一个http服务器的主干部分.这部分代码只会执行在一个线程上 ...
- iOS 5 故事板进阶(2)
让我们回到游戏排行窗口Ranking.创建一个 UITableViewController子类,命名为 RankingViewController. 编辑 RankingViewController. ...
- Latex中Matlab代码的环境
需要用到listings宏包 使用方法: 导言区\usepackage{listings}\lstset{language=Matlab} %代码语言使用的是matlab\lstset{br ...
- Dapper 嵌套对象查询
我有这样一个一对一关系的表结构:User->UserInfo User: /// <summary> /// 用户 /// </summary> [Serializabl ...
- RESTful Android
RESTful Android API 定义 约定 回复中默认包含标头: Content-Type: application/json;charset=UTF-8 异步操作以(*)号标记 大多数异步操 ...
- LinkServer--访问远程数据表三种方式
在TSQL中访问远程数据库有三种方式:1.OPENROWSET2.OPENDATASOURCE3.LinkServer 在使用openrowset/opendatasource前搜先要启用Ad Hoc ...
- asp.net—策略模式
一.什么是策略模式 定义:定义一系列算法,把一个个算法封装成独立类并实现同一个接口,使得它们之间可以相互替换. 二.怎么使用策略模式 首先模拟一个场景:有一个用户想买车. 可以有多种方式买车: (1 ...
- Tasks遇到的一些坑,关于在子线程中对线程权限认证。
一般情况下,不应该在执行多线程认证的时候对其子线程进行身份认证,如:A线程的子线程B和子线程C. 当使用 Parallel.ForEach方法时,只有自身线程能够拥有相对应的权限,其子线程权限则为NU ...
- Day 38 Semaphore ,Event ,队列
什么是信号量(multiprocess.Semaphore) 互斥锁同时只允许一个线程更改数据,而信号量semaphore是同时允许一定数量的线程更改数据. 假设商场里有4个迷你唱吧 ,所以通过同时可 ...
- [LeetCode] Minimum Number of K Consecutive Bit Flips 连续K位翻转的最小次数
In an array A containing only 0s and 1s, a K-bit flip consists of choosing a (contiguous) subarray o ...