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 ...
随机推荐
- day8 异常处理
异常和错误 part1:程序中难免出现错误,而错误分成两种 1.语法错误(这种错误,根本过不了python解释器的语法检测,必须在程序执行前就改正) 2.逻辑错误(逻辑错误) part2:什么是异常 ...
- (KMP)剪花布条 -- hdu -- 2087
http://acm.hdu.edu.cn/showproblem.php?pid=2087 剪花布条 Time Limit: 1000/1000 MS (Java/Others) Memory ...
- Activity生命流程
做Android的同学说起 Activity,那绝对是熟悉的不能再熟悉了,但是越熟悉的东西往往越陌生.我们真的了解她吗?她是我们所认识的那样吗?或许是,或许不是!了解与否, 让我们往下看.首先借And ...
- hdu 1266 Reverse Number
题目 一道水题,但是超时了几次(Time Limit Exceeded) 题中说:then n 32-bit integers follow.私以为可以用int来做,结果就一直超时,博客之,发现全是用 ...
- Bitcoin
看李笑来老师的2013演讲——Bitcoin is not virtual currency,it is a real world. 1.由于bitcoin的算法中进行有上限量的发布,所以这是不会出现 ...
- Python学习-21.Python的代码注释
在Python中有两种注释,一种是普通注释,另一种是文档注释. 普通注释是使用#开头 print('output something') # here is comment 而Python中多行注释也 ...
- Visual Studio模板
转载自MSDN,此文仅作参考. http://msdn.microsoft.com/zh-cn/library/6db0hwky(VS.80).aspx 1. 如何导入“项目模板(Project Te ...
- 从 exe.config 读取appSettings 中的配置数据
右键解决方案,添加引用--> System.Configuration.dll 在exe.config 中添加数据 <appSettings> <add key=" ...
- 深入浅出“跨视图粒度计算”--3、EXCLUDE表达式
本文由 网易云发布. 深入嵌入“跨视图粒度计算”的前面两篇分别讲了 1.理解数据的粒度 2.INCLUDE表达式 这一篇讲一下EXCLUDE表达式的用法. EXCLUDE,中文译为“排除”,顾名思义 ...
- python 以行为单位进行字符串的切割
可以使用str 的 splitlines() 方法 实现以行为单位 进行字符串的切割, keepends=False 不保留\n符号, kendends=True 保留\n符号 my_str = &q ...