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 ...
随机推荐
- arcgis api for flex 开发入门(一)环境搭建
http://www.cnblogs.com/wenjl520/archive/2009/06/02/1494514.html arcgis api for flex 开发入门(一)环境搭建arcgi ...
- 整数重复的第n位计算公式
513不停的重复形成513513513....,求第n位是几的计算公式.
- Hdu1969 Pie 2017-01-17 13:12 33人阅读 评论(0) 收藏
Pie Time Limit : 5000/1000ms (Java/Other) Memory Limit : 65536/32768K (Java/Other) Total Submissio ...
- OKHttp概览
1,整体思路 从使用方法出发,首先是怎么使用,其次是我们使用的功能在内部是如何实现的,实现方案上有什么技巧,有什么范式.全文基本上是对 OkHttp 源码的一个分析与导读,非常建议大家下载 OkHtt ...
- Fig 7.2.4 & Fig 7.3.2
Fig 7.2.4 \documentclass[varwidth=true, border=2pt]{standalone} \usepackage{tkz-euclide} \begin{docu ...
- Get User CustomNotificationAddresses
select pv.StringValue, * from tbl_Identity i left join tbl_PropertyValue pv on pv.ArtifactId=conv ...
- Alwayson--使用证书创建高可用性组
--场景: --有服务器SQLNode11,SQLNODE21,SQLNODE31三台在同一故障转移群集SQLNode01中 --的数据库服务器,安装SQL SERVER 2012 并配置启动alwa ...
- dstat常用参数组合
io/if/vm三合一 dstat -cdlmnpsy dstat --top-mem --top-cpu --top-io
- nginx优化笔记(keepalive、https等)
一.nginx之tcp_nopush.tcp_nodelay.sendfile 1.TCP_NODELAY你怎么可以强制 socket 在它的缓冲区里发送数据?一个解决方案是 TCP 堆栈的 TCP_ ...
- ie下警告console未定义
低版本IE6/7/8/9浏览器没有定义console对象,所以代码会中断执行.自己测试,ie11也没有(打开控制台的情况下可以用) 可以用如下代码完美解决. window.console = wind ...