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 ...
随机推荐
- TableView编辑状态下跳转页面的崩溃处理
29down votefavorite 12 I have a viewController with a UITableView, the rows of which I allow to edit ...
- Js中 关于top、clientTop、scrollTop、offsetTop
网页可见区域宽: document.body.clientWidth; 网页可见区域高: document.body.clientHeight; 网页可见区域宽: document.body.offs ...
- 为UITextView添加通知..来检测UITextView内容的改变
self.mTextView =[[UITextView alloc]initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH - 100, 28)]; se ...
- python与JavaScript中正则表达式如何转换
使用python爬取网站数据的时候,总会遇到各种各样的反爬虫策略,有很大一部分都和JavaScript(以下简称为JS) 有关.在破解这些JS代码的过程中,经常会遇到模拟JS正则表达式的情况,因此,今 ...
- Codeforces735C Tennis Championship 2016-12-13 12:06 77人阅读 评论(0) 收藏
C. Tennis Championship time limit per test 2 seconds memory limit per test 256 megabytes input stand ...
- PGF基本图形对象
\documentclass{article} \usepackage[active ,tightpage ,xetex ]{ preview} \usepackage{tikz} \begin{do ...
- Grafana展示DNS解析延时
首先一个完整的监控肯定会包含三个部分:1.数据收集部分.2.数据存储部分.3.数据展示部分,今天我也是从这三个方面来实现这个监控的. 数据收集(SHELL 脚本) 没有想到比较好的方法来采集数 ...
- Postgresql 創建觸發器,刪除觸發器和 禁用觸發器
CREATE OR REPLACE FUNCTION XF_VIP_AFUPD_WX() RETURNS trigger AS $$ DECLARE i_count integer; s_wx_ope ...
- C# 使用ftp下载一个文件夹下的所有文件,包括子目录文件夹
这篇博客给大家补充一个方法,就是得到一个目录下的所有文件名称.在前端调用,大家写一个递归去遍历就可以了,我在这里就不在写了.具体ftp下载的方法在我的另一篇博客里有,需要的可以去看一下. /// &l ...
- DropDownList切换选择,服务器控件Repeater未更新
将EnableViewState属性设置为false,这样禁止服务器控件使用视图状态,也就是禁止发送给浏览器HEML中的缓存副本, 每次都会使用新数据. 一旦页面的控件很多,频繁的传递控件状态值对网络 ...