我试图通过字节码操作(使用ASM framework
)来记录实例级别(或类级别)对象初始化或对象分配
这样的事情:
这是我声明一些实例变量的类:
class DeclarationTestClass1{
/** Assume This Class has some public instance variables **/
private MultipleDeclarationTestClass multiClass = null;
private List<String> arrayList1_String = null;
public static Hashtable<Integer,Integer> staticHashTable = null;
public List<String> getArrayList1_String() {
return arrayList1_String;
}
public void setArrayList1_String(List<String> arrayList1_String) {
this.arrayList1_String = arrayList1_String;
}
}
现在,我想做:
DeclarationTestClass1 object1 = new DeclarationTestClass1();
MultipleDeclarationTestClass object1 .object1_innerObject = new MultipleDeclarationTestClass();
RecordingClass.recordingMethod(object1.arrayList1_String = new ArrayList<String>());
RecordingClass.recordingMethod(object1 .object1_innerObject.someMap = new HashMap<String,String>());
现在,当我使用ASMifier查看所需类的输出时,我可以看到在调用实际putfield
之前,有一个DUP_X1
被调用。
现在,我的理解是,由于实例级对象是通过另一个对象引用的(即:object1.arrayList1_String = new ArrayList<String>()
,所以栈的第二个字保存了引用它的对象(即object1
)。
如果我错了,请纠正我。
但是,我无法理解,在第二种情况下,当实例级别对象通过另一个额外对象(即:object1 .object1_innerObject.someMap = new HashMap<String,String>()
)引用时,它在堆栈中有另一个额外的对象,对吗?
所以我的问题是:
1)为什么在第二种情况下,还会调用DUP_X1
?
2)我在asm中使用COMPUTE_MAXS
标志,其中asm为我计算最大堆栈大小。因此,如果我不覆盖visitMaxs
中的MethodVisitor
方法,这种重复会产生任何影响。
非常感谢这方面的任何帮助。
答案 0 :(得分:2)
作为Antimony has pointed out,您是否拥有x.y = foo
或x.y.z.a.b.c = foo
形式的代码与堆栈大小无关。
对于链的每个节点,getfield
指令将从堆栈中弹出字段所有者实例,并将字段值推送到堆栈(将成为下一个节点的所有者)。
所以唯一有趣的部分是putfield
。它将从堆栈,字段所有者和新值中弹出两个值。由于您使用的格式为method(x.y=foo)
,因此您需要第二次使用该值,以便将其传递给方法。
因此需要一种dup
,但由于后续putfield
将使用两个项目,因此必须将值的副本下推到字段所有者下方:
dup_x1: …, owner, value] → …, value, owner, value]
putfield: …, value, owner, value] → …, value]
invokestatic: …, value] → …]
答案 1 :(得分:1)
在2个间接超过1的情况下,你实际上不会在堆栈上有任何额外的东西,因为分配只需要最后一个对象。想一想。
object1.object1_innerObject.someMap = new HashMap<String,String>())
在此代码中,您评估object1.object1_innerObject
(称之为t1
),然后new HashMap<String,String>()
(称之为t2
),最后执行分配,{{1 }}
等效字节码(假设object1在局部变量槽1中)
t1.someMap = t2
堆叠中最多有3个项目,但这与您aload_1
getfield object1type object1_innnerObject innerobjecttype
new HashMap
dup
invokespecial java/util/HashMap <init> ()V
setfield innerobjecttype someMap java/util/HashMap
只有一样。