Question

I was trying to find some approximization to address on heap , and you guys gave me the function System.IdentityHashCode(Object).

The problem is - this function doesn't fit for primitive types. I'll explain why.

I'm given as input Java compiled program - class file. My goal is to plot some graphs that will contain some information about variable access between time. I have no idea of how the code looks in advance , and my tactic is instrumentation of my own bytecode for every LOAD and STORE instruction. I'm using ASM Java Bytecode Instrumentation.

Therefore, I can't do something like:

identityHashCode(Integer.valueOf(...))

because I have no indication whether the type is int, double, long, etc.

I want to be able to determine between different instances of the same class:

For example :

class foo {
int a;
}
foo b;
foo c;
b.a++;
c.a++;

But when it comes to bytecode , there is no relation between the name "b" / "c" and the attribute a. All I "see" is that a is incremented. Both are regarded as a ! if that was Object a I could have used System.identityHashCode() to distinguish between them. But I can't.

To make myself clear, look at the following example:

package manipulate;

public class Test {
        int c;
        public static void main(String[] args) {
            Test a=new Test();
            Test b=new Test();
            a.c++;
            b.c++;
        }
    }

which will be translated (main function) to the following bytecode:

   L0
    LINENUMBER 7 L0
    NEW manipulate/Test
    DUP
    INVOKESPECIAL manipulate/Test.<init>()V
    ASTORE 1
   L1
    LINENUMBER 8 L1
    NEW manipulate/Test
    DUP
    INVOKESPECIAL manipulate/Test.<init>()V
    ASTORE 2
   L2
    LINENUMBER 9 L2
    ALOAD 1
    DUP
    GETFIELD manipulate/Test.c : I
    ICONST_1
    IADD
    PUTFIELD manipulate/Test.c : I
   L3
    LINENUMBER 10 L3
    ALOAD 2
    DUP
    GETFIELD manipulate/Test.c : I
    ICONST_1
    IADD
    PUTFIELD manipulate/Test.c : I
   L4
    LINENUMBER 11 L4
    RETURN

And as you can see, what I've got on the stack is just the value of the integer c. Therefore, given that code, I can't determine between these two c's!

Was it helpful?

Solution

What i've got is java bytecode . I dont have b or c and I'm not aware of them . I only have the value of a on the stack

If you have local variables on the stack, they have variable numbers. These numbers are local to the stack frame, in which the method is executing, and two variables are same if they have the same number.

If you have the two primitive values in your evaluation (argument/operand/result) stack, they are same (in a similar sense as for variables) if they exist at the same time at the same stack index.


In your example, you see that the two GETFIELD manipulate/Test.c : I instructions operate each on the current value on the stack (which is put there by ALOAD 1 or ALOAD 2). This current value is the object to which your variable belongs, so you could insert there your counting code for this object (do a DUP first).

OTHER TIPS

Primitives do not have identities. They are compared by value, not by reference. The address in memory of a primitive in a local variable is likely to be in a register or on the stack, and the location of a primitive member of an array or object is related to the heap address of its parent.

Java does not provide any standardized memory access facilities, and alternatives, like System.identityHashCode do not extend to them.

Calling System.identityHashCode with a primitive will cause a spurious boxing to occur which will give nonsensical results.

If you really need to know the location of a primitive member, you can write C code with JNI bindings to get a handle to a java object, get a pointer, and convert that to a java integral type of the right width, but your best bet is to probably find some other way to do what you're trying to do.

One other option is to use the existing java debugger hooks : http://download.oracle.com/javase/6/docs/technotes/guides/jpda/architecture.html#jdi

I'm not sure I understand the question, you want to know if b.a is infact the same variable as c.a?

In your case, b.a will be the same as c.a if b==c. If you declare a static, it will be shared between all instances of foo.

When you asked about memory addresses, and got the identityhashCode answer, the key phrase was "some approximation". There is no guarantee that this value will be the memory address, and even the most aggressive assertion is that it is a mapping from the address to an integer. You absolutely cannot reliably determine the address of an object in Java, and shouldn't even think about trying with primitives. For one thing there is no guarantee that the compiler won't move them. There isn't even a guarantee that the variable ever has an address.

If you want to determine whether two objects are the same, you can use "==". The question doesn't even make sense with primitives, and you shouldn't be doing it.

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