Question

I am trying to record instance level (or class level ) object initialization or object assignments through bytecode manipulation (using ASM framework )

Something like this :

This is the class where I am declaring some instance variables :

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;
    }
}

Now, I want to do :

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>());

Now when I see the output of the desired class using ASMifier , I can see that before the actual putfield is called , there is one DUP_X1 getting called.

Now , my understanding is that as the instance level object is referred through another object (i.e : object1.arrayList1_String = new ArrayList<String>() , second word of the stack holds the object through which it is referred (i.e object1 ). Please correct me if I am wrong.

But , what I can not understand , in the second scenario , when the instance level object is reffered through another extra object (i.e: object1 .object1_innerObject.someMap = new HashMap<String,String>()) , it has another extra object in the stack , right ?

So my questions are :

1) Why in the second scenario also , DUP_X1 is called ?

2) I am using COMPUTE_MAXS flag in asm , by dint of which asm calculates the max stack size for me . So , will this duplicating have any impact if I do not override visitMaxs method in MethodVisitor.

Any help in this regard , is much much appreciated.

Was it helpful?

Solution

As Antimony has pointed out, it doesn’t matter to the stack size whether you have code of the form x.y = foo or x.y.z.a.b.c = foo.

For each node of the chain the getfield instruction will pop the field owner instance from the stack and push the field value onto the stack (which will become the owner for the next node).

So the only interesting part is the putfield. It will pop two values from the stack, the field owner and the new value. Since you are using an expression of the form method(x.y=foo) you need the value a second time, for passing it to the method.

So a kind of dup is required, but since the follow-up putfield will consume two items, the copy of the value must be pushed down below the field owner:

dup_x1:       …, owner, value]        → …, value, owner, value]
putfield:     …, value, owner, value] → …, value]
invokestatic: …, value]               → …]

OTHER TIPS

You actually wouldn't have anything extra on the stack in the case of 2 indirections over 1, because only the last object is needed for the assignment. Think about it.

object1.object1_innerObject.someMap = new HashMap<String,String>())

In this code, you evaluate object1.object1_innerObject (call it t1), then new HashMap<String,String>() (call it t2), and finally the assignment is performed, t1.someMap = t2.

Equivalent bytecode would be (assuming object1 is in local variable slot 1)

aload_1
getfield object1type object1_innnerObject innerobjecttype
new HashMap
dup
invokespecial java/util/HashMap <init> ()V
setfield innerobjecttype someMap java/util/HashMap

You have a maximum of 3 items on the stack, but that's the same as if you were only doing object1.someMap.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top