转载: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. 百度Webuploader 大文件分片上传(.net接收)

    版权所有 2009-2018荆门泽优软件有限公司 保留所有权利 官方网站:http://www.ncmem.com/ 产品首页:http://www.ncmem.com/webapp/up6.2/in ...

  2. (转)C#静态方法使用经验浅谈

    转自:http://developer.51cto.com/art/200908/147734.htm C#静态方法有什么弊端? 我们在实际的开发过程中会注意到C#静态方法对于我们程序的影响,那么有哪 ...

  3. 求解1^2+2^2+3^2+4^2+...+n^2的方法(求解1平方加2平方加3平方...加n平方的和)

    利用公式 (n-1)3 = n3 -3n2 +3n-1 设 S3 = 13 +23 +33 +43 +...+n3 及 S2 = 12 +22 +32 +42 +...+n2 及 S1 = 1 +2 ...

  4. Asp.net mvc验证用户登录之Forms实现

    这里我们采用asp.net mvc 自带的AuthorizeAttribute过滤器验证用户的身份,也可以使用自定义过滤器,步骤都是一样. 第一步:创建asp.net mvc项目, 在项目的App_S ...

  5. js 面向对象 继承机制

    根据w3cschool上的描述:共有3种继承方法(对象冒充,原型链,混合) 1.对象冒充:构造函数ClassA使用this关键字给所有属性和方法赋值,使ClassA构造函数成为ClassB的方法,调用 ...

  6. Postgresql 锁查看

    之前版本 PostgreSQL 的 pg_stat_activity 视图的 waiting 字段判断会话是否等待锁资源(通俗地讲, waiting 值为true表示申请不到锁资源处于等待状态),但是 ...

  7. 窗口与导航-----Selenium快速入门(十三)

    前面所讲的,大部分是WebDriver这个接口以及相关的类的使用.而本文所讲的窗口与导航,也是里面的内容,而且非常简单,目测就能学会. 一.窗口,也就是window,这里的窗口是指浏览器窗口.他的方法 ...

  8. NetCore入门篇:(七)Net Core项目使用Controller之二

    一.简介 1.说明Post,Get定义的区别. 2.说明如何路由定义. 二.Get.Post定义 1.api不定义访问方式时,同时支持get 和 post.如果定义某种方式,则仅支持某种方式.具体看代 ...

  9. xt

    using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...

  10. MongoDB VUE的下载及安装

    下载: mongo vue官网地址:http://www.mongovue.com/ 安装: 很简单,注意的是:在提示buy 和 OK  的时候点击OK即可: 连接: 默认连接(无用户名密码): 在启 ...