我写了一个java代理来测试一个开源的基准测试commons-net
,但是我得到了以下错误:
java.lang.VerifyError: Bad type on operand stack
Exception Details:
Location:
org/apache/commons/net/util/SubnetUtils$SubnetInfo.<init>(Lorg/apache/commons/net/util/SubnetUtils;)V @9: invokestatic
Reason:
Type uninitializedThis (current frame, stack[2]) is not assignable to 'java/lang/Object'
Current Frame:
bci: @9
flags: { flagThisUninit }
locals: { uninitializedThis, 'org/apache/commons/net/util/SubnetUtils' }
stack: { 'org/apache/commons/net/util/SubnetUtils', uninitializedThis, uninitializedThis }
Bytecode:
0x0000000: 12ca b800 cf2a 2b5f 59b8 00d3 5fb5 0002
0x0000010: 2ab7 0003 b800 d6b1
at...
和
Exception in thread "Thread-1" java.lang.VerifyError: Bad type on operand stack
Exception Details:
Location:
org/apache/commons/net/tftp/TFTPServer$TFTPTransfer.<init>(Lorg/apache/commons/net/tftp/TFTPServer;Lorg/apache/commons/net/tftp/TFTPPacket;)V @10: invokestatic
Reason:
Type uninitializedThis (current frame, stack[2]) is not assignable to 'java/lang/Object'
Current Frame:
bci: @10
flags: { flagThisUninit }
locals: { uninitializedThis, 'org/apache/commons/net/tftp/TFTPServer', 'org/apache/commons/net/tftp/TFTPPacket' }
stack: { 'org/apache/commons/net/tftp/TFTPServer', uninitializedThis, uninitializedThis }
Bytecode:
0x0000000: 1301 84b8 0189 2a2b 5f59 b801 8d5f b500
0x0000010: 012a b700 022a 035f 59b8 018d 5fb5 0003
0x0000020: 2a01 5f59 b801 8d5f b500 042a 2c5f 59b8
0x0000030: 018d 5fb5 0005 b801 90b1
at...
有趣的是,这两个错误都是在内部类中抛出的,并且堆栈帧非常相似。我猜这只是在初始化内部类时发生的,因为我在堆栈中看到了uninitializedThis
。
我的MethodVisitor适配器很长很复杂,所以我没有在这里发布它。我用它来跟踪method_start
,method_end
,new_object
,object_modify
,PUTFIELD
,PUTSTATIC
,我需要通过调用INVOKESTATIC
来记录修改后的对象和新对象。我在NEW
之后注解了插入的指令DUP
和INVOKESTATIC
,但它仍然报告相同的错误。我想如果我能知道内部类是如何初始化的,调试会容易得多。
这两个<init>
方法的源代码:
第一次
我已经在我的MethodVisitor适配器类中找到了错误代码。我的意思是,当我注解这些代码时,错误似乎消失了。但我仍然不知道为什么会发生这个错误。SubnetInfo
的构造函数似乎没有修改任何字段的操作。我猜可能是因为内部类初始化的一些隐藏特性?
public void visitFieldInsn(int opc, String owner, String name, String desc){
// Access Static Fields
if ((opc == GETSTATIC || opc == PUTSTATIC) && shouldIncludeClass(owner)){
mv.visitLdcInsn(owner);
mv.visitMethodInsn(INVOKESTATIC, MyClass, MyMethod,
"(Ljava/lang/String;)V", false);
}
if (...){
if (opc == PUTFIELD){
Type t = Type.getType(desc);
if (t.getSize() == 2){
mv.visitInsn(DUP2_X1);
mv.visitInsn(POP2);
}else {
mv.visitInsn(SWAP);
}
mv.visitInsn(DUP);
mv.visitMethodInsn(INVOKESTATIC, MyClass,
MyClass.TRACE_OBJ_MODIFY, "(Ljava/lang/Object;)V", false);
if (t.getSize() == 2){
mv.visitInsn(DUP_X2);
mv.visitInsn(POP);
}else {
mv.visitInsn(SWAP);
}
}else if (opc == PUTSTATIC){
mv.visitMethodInsn(INVOKESTATIC, MyClass,
MyClass.TRACE_PUTSTATIC, "()V", false);
}
}
mv.visitFieldInsn(opc, owner, name, desc);
}
我只跟踪了SubnetInfo
的构造函数中的一条PUTFIELD
指令。在我的日志中:
Transform: org/apache/commons/net/util/SubnetUtils$SubnetInfo
**** PUTFIELD found ****
**** className org/apache/commons/net/util/SubnetUtils$SubnetInfo ****
**** methodName <init> ****
**** opc PUTFIELD ****
**** owner org/apache/commons/net/util/SubnetUtils$SubnetInfo ****
**** name this$0 ****
**** desc Lorg/apache/commons/net/util/SubnetUtils; ****
这个PUTFIELD
指令是什么意思?把外部类的对象放到内部类的字段this$0
上?有没有办法识别内部类的初始化?
1条答案
按热度按时间hwazgwia1#
内部类会先调用this的init函数,与普通类不同的是constructor.you在init操作后必须将this赋给var。