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 ...
随机推荐
- Hive 1.2.1&Spark&Sqoop安装指南
目录 目录 1 1. 前言 1 2. 约定 2 3. 服务端口 2 4. 安装MySQL 2 4.1. 安装MySQL 2 4.2. 创建Hive元数据库 4 5. 安装步骤 5 5.1. 下载Hiv ...
- 关于Python Package下的Module import方式[转]
2012年有一个目标我没有达成,那就是深入学习和使用Python语言.这个目标被其他学习任务和工作无情的抢占了,当然最主要的原因还是我重视不够^_^. 近期恰逢有一些Python工程的开发工作要做,就 ...
- 理解Defer、Panic和Recover
刚开始的时候理解如何使用Defer和Recover有一点怪异,尤其是使用了try/catch块的时候.有一种模式可以在Go中实现和try/catch语句块一样的效果.不过之前你需要先领会Defer.P ...
- struts2从浅至深(六)总结
在我认为strust2的作用就是 1.主要跟前端交互的框架数据提交先经过struts 2.起到对数据的过滤,接受数据 3.把数据显示到前段,具有很成熟的ognl技术,用起来特别方便 4.还提供了跟前段 ...
- 最佳编程字体:M+
英文原文:The Best Font for Programming: M+ 程序员的最佳等宽字体是 M+. 一个偶然机会遇到了这个字体,在命运多舛的 kod 编辑器体验了.这个字体非比寻常,我坚持 ...
- iOS Development和iOS Distribution有什么区别
http://zhidao.baidu.com/link?url=T9od33JuA7jjxzfyV-wOjuVLSNUaqpc9aoCu2HjfYfHBuRLW1CNDii0Bh9uvG6h-GeJ ...
- unlimited channel buffer in Go
channel buffer可以事先分配大小,但是这些是需要占用内存的,事先分配几G内存给一个channel很浪费资源的,所以怎样创建一个无限的channel buffer呢?比较naive的写法就是 ...
- 使用n g r o k将本地主机URL暴露给互联网
在本地开发对接第三方服务的时候,对方有的时候会要求我们提供一个线上的URL地址.例如微信登录 1.下载ngrok https://ngrok.com/download 顺便注册一个账号(使用GitHu ...
- 毕业回馈-89C51之数码管的使用
7段码的数码管由7个LED等共同组成,根据公共端的不同有共阴和共阳之分.现在很多数码管在7段码的基础上加了一个.即dp,其内部结构如下图所示: 公共端为LED灯的阴极,所以为共阴极接法: 公共端为阳极 ...
- laravel5的Bcrypt加密方式对系统保存密码的小结
laravel5文档介绍 //对 A 密码使用Bcrypt 加密 $password = Hash::make('secret'); //你也可直接使用 bcrypt 的 function $pass ...