在 JVM 字节码中添加空对象检查

Adding a check for null object in JVM bytecode

我正在使用 ASM 修改任何 java class 的字节码,以便为每个对象添加空值检查。

例如,对于这段代码:

Object a = new Object();
a.doSomething();

我想修改字节码,使其看起来像这样:

Object a = new Object();
assertNotNull(a);
a.doSomething();

或者这个:

Object a = new Object();
if(a != null){
a.doSomething();}
else return 1 //or throw exception

我卡住了,因为我不知道 ALOAD 对应的数字是多少。我认为 ALOAD 总是与 ALOAD 1(或这种格式的 ALOAD n)一起使用。我该怎么做才能获得 ALOAD 附带的号码?这是我到目前为止的工作(使用 Junit assertNotNull)

/*
 * Use JUnit assertNotNull to check object/item for null
 */
private void addAssertNullMethod() {
    //need to add ALOAD here, but I don't know the location of the object on the stack.
    mv.visitMethodInsn(Opcodes.INVOKESTATIC, "org/junit/Assert", "assertNull", "(Ljava/lang/Object;)V", false);
    mv.visitEnd();
}

您需要 DUP 字节码。

ALOAD指的是局部变量,但是不能给给定的对象分配局部变量槽。在调用 doSomething() 之前,对象引用已经放在表达式堆栈中(使用 ALOAD 字节码或其他一些 - 这无关紧要)。所以你只需要复制这个对象引用(使用DUP)然后调用你的断言方法。