转载: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

  • JDK-8020204

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

Source

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

Source
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

Source

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

Source

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的更多相关文章

  1. Gen类的字符串操作

    public void t(String d){ final String str = "b"; String s = "a"+"c"+st ...

随机推荐

  1. Chrome报错:跨域问题处理( Access-Control-Allow-Origin)_ 用于本地测试的快捷解决方法

    报错提示如下: XMLHttpRequest cannot load http://www.xxxx.com/264/Data/GetScreenInfo. No 'Access-Control-Al ...

  2. vs2015 cmd.exe已退出 代码为1

    https://blog.csdn.net/changbin91/article/details/42874377?utm_source=blogxgwz0 https://blog.csdn.net ...

  3. Android之ubuntu源码开发环境搭建笔记

    昨天,把电脑主机全换了,因此之前的工作环境得重新搭建,我是既开心又纠结,开心的是可以用高配置的电脑,纠结的是搭环境比较麻烦,稍有不慎,就会导致源代码编译不过,前功尽弃.为了减少工作量,以及避免不必要掉 ...

  4. Python学习-33.Python中glob模块的一些参数

    glob模块中有一个叫glob的方法可以获取某个目录下的文件. import glob temp=glob.glob("E:\\Temp\\*.txt") print(temp) ...

  5. Tmux入门教程

      对于程序员来说效率绝对是最重要的,那我们今天就来介绍下一个能极大提高工作效率的软件Tmux.   Tmux 是一个工具,用于在一个终端窗口中运行多个终端会话.不仅如此,你还可以通过 Tmux 使终 ...

  6. ArcGIS下图层范围不正确的两种处理方式

    ArcGIS下图层范围不正确,偶尔能碰上这种情况,主要表现为“缩放至图层”时,其显示范围与该图层内所有要素的外包围盒范围不一致.针对这个问题,有两种解决办法. 方法一:导出数据.新创建含有要素的Sha ...

  7. 记录一下将SqlLocalDb数据迁移到Sql Server Express2017的过程!

    当初为了开发方便,使用了SqlLocalDb,然后再测试期产生了很多有用的数据,客户说不能删除了.麻烦 先将数据库文件下载回来,然后安装SSMS,在连接数据库地址那里,填写“(LocalDB)\MSS ...

  8. 如何把OpenWrt安装到PC?

    前言 什么是openwrt? 它是一个适用于路由器的Linux发行版.和其他Linux发行版一样,它也内置了包管理工具,你可以从一个软件仓库里直接安装软件.OpenWrt可以用在所有需要嵌入式Linu ...

  9. DDoS防护之TCP防护

    本文由  网易云 发布. TCP协议,相信对于每一个开发工程师都不陌生.由于该协议是一个面向连接,可靠的特性,广泛应用于现在互联网的应用中.如常见的Web.SSH.FTP等都是基于TCP协议.目前TC ...

  10. Segment Tree-732. My Calendar III

    Implement a MyCalendarThree class to store your events. A new event can always be added. Your class ...