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 ...
随机推荐
- 201709012工作日记--activity与service的通信机制
service生命周期 Service主要包含本地类和远程类. Service不是Thread,Service 是android的一种机制,当它运行的时候如果是Local Service,那么对应的 ...
- [翻译Joel On Software]选择一门语言/Choosing a language
Joel on Software Choosing a language 选择一门语言 by Joel Spolsky Sunday, May 05,2002 Why do developerscho ...
- EBS MOAC相关
http://blog.csdn.net/rfb0204421/article/details/9306929 支持MOAC功能的Form开发步骤 分类: FORM2013-07-12 10:01 1 ...
- Debezium for PostgreSQL to Kafka
In this article, we discuss the necessity of segregate data model for read and write and use event s ...
- 学习总结---INNODB 事务并发
目前在做一个OLTP的数据库系统,批量读写和随机读写并发,情况比较复杂.INNODB是我们的MYSQL引擎,他的主要特点是读操作可以不受阻塞,而修改操作会加锁.如何才能最高效的使用innodb是我们需 ...
- 项目笔记---WPF多语言方案
近期由于朋友邀请帮忙给一个开源的游戏“外挂”做一个I18N的解决方案,恰好也是WPF做的,之前有过相关经验,就忙了一个星期终于搞定了,已经提交给作者了,现在这里做一个分享. 这里分享下我个人Fork的 ...
- Global.asax和HttpModule的执行顺序
Application_Start-->用户自定义的HttpModule-->Application_BeginRequest (注册->调用) 看到Init方法(在用户自定义的 ...
- [.net 多线程]线程基础
一.线程状态 1.新建状态(New): 当用new操作符创建一个线程时, 例如new Thread(r),线程还没有开始运行,此时线程处在新建状态. 当一个线程处于新生状态时,程序还没 ...
- [Xamarin]我的Xamarin填坑之旅(一)
一想到明天是星期五,不对,是今天,心里就很激动,毕竟明天没课.激动之余,来写一篇博客,记录一下最近踏坑Xamarin开发校园助手APP的一些事儿.也许更像是一篇流水账. 在扯Xamarin之前,有必要 ...
- 《Python黑帽子:黑客与渗透测试编程之道》 Web攻击
Web的套接字函数库:urllib2 一开始以urllib2.py命名脚本,在Sublime Text中运行会出错,纠错后发现是重名了,改过来就好: #!/usr/bin/python #coding ...