ASM - 拦截在Method外部进行的字段访问

时间:2012-12-29 15:37:11

标签: java instrumentation java-bytecode-asm

我目前正在使用ASM拦截所有在目标应用程序中改变字段值的尝试,这正在按预期工作,因为ASM允许您在方法或构造函数代码段之前添加或附加指令。

但是,在我看来,它是一个相当常见的开发人员范例,用于初始化方法或构造函数范围之外的字段,例如:

public class Example{

  //--VARIABLE INITIALIZATION OUTSIDE METHOD OR CONSTRUCTOR SCOPE ---
  private String aString = "A String Value";

  //zero argument constructor
  public Example(){

  }

  //all other methods.


}

我的问题是:如何处理以这种方式拦截字段访问的任务,即方法或构造函数的上下文?

2 个答案:

答案 0 :(得分:2)

这看起来好像它在源代码中的构造函数之外,但实际上在字节码中,初始化器都是构造函数的一部分 - 它们被编译器“移动”到构造函数中。在隐式或显式super()调用之后放置,而之前构造函数的其余代码。特别是这意味着如果你有这样的情况:

class Super {
  protected Super() {
    doSomeStuff();
  }

  protected abstract void doSomeStuff();
}

class Sub extends Super {
  private int number = 1;

  public Sub() {
    super();
    System.out.println("in Sub(): " + number);
  }

  protected doSomeStuff() {
    System.out.println("in doSomeStuff(): " + number);
  }
}

然后new Sub();将打印

in doSomeStuff(): 0
in Sub(): 1

因为in doSomeStuff打印在Sub字段初始化程序运行之前发生。

答案 1 :(得分:1)

所有代码都在方法内部(构造函数和静态初始化程序也是方法)。

您有字段的初始值,您可以在字段声明中看到,但编译器似乎没有使用这些。

private String aString = "A String Value";

//zero argument constructor
public Example(){

}

相同
private String aString;

//zero argument constructor
public Example(){
    super();
    aString = "A String Value";
}