3

What I'm trying to is to get 'hashCode()' value of the object that calls a specific method in Java. For example,

public class Caller {
    public void aMethod() {
        Callee calleeObj = new Callee();
        calleeObj.aSpecificMethod();
        //do something
    }
}

What I want to know is Caller's hashCode() value which calls calleeObj.aSpecificMethod() during the runtime. It is for drawing an Object diagram like below.

enter image description here

As a constraint, I only can modify '.class' files using bytecode instrumentation techniques.

To do that, I've tried Javassist library to instrument inside Callee.aSpecificMethod() but this way cannot get the caller's object. The reason seems obvious because instrumented code on 'Callee.aSpecificMethod()' only can access codes on Callee class, not Caller class.

Is there any way to capture the hashCode() value of caller's object using Javassist? I'm considering ASM 5.0 also, but using ASM 5.0 is the last option because I've built many code based on Javassist until now.

byron1st
  • 969
  • 1
  • 13
  • 35
  • 3
    Change the method? `calleeObj.aSpecificMethod(this.hashCode())` – user253751 May 25 '15 at 08:16
  • Can you change the class also for the caller-object? If so it's just a matter of adding an argument as @immibis suggests. Otherwise I don't think this is possible. (What should happen if the `hashCode` is called from a static context? I.e., there is no calling object.) – aioobe May 25 '15 at 08:22
  • Hi, you may want to try that with aop stuff (aspectj) to achieve that? – kucing_terbang May 25 '15 at 09:47
  • @immibis Yeap, but modifying every method's parameters by using Javassist is not realistic for me. – byron1st May 26 '15 at 01:40
  • @aioobe I agree with your comment that there is no option without passing the argument. I consider to use ASM or other ways. – byron1st May 26 '15 at 01:41
  • @kucing_terbang Yeap. Exactly. Using AspectJ is an easy way to do what I want, but I exclude AspectJ because, as far as I know, it requires source code(.java) and they should be compiled with a special compiler only for AspectJ. So, I've tried byte code injection techniques, which can be used along with -javaagent: command. – byron1st May 26 '15 at 01:44

2 Answers2

4

As said by others, there is no way of the invoked method getting hands on the caller object, but so far, nobody pointed you to the reason why this will never be possible:

The big misconception about your request is that you assume that there has to be a “caller object”. But there is no such thing. Your method might get invoked by static methods, e.g. right from the main method of an application, but also from class initializers or from constructors, even during the super constructor invocation, in other words, at places, where an object exists in the context of the invocation but hasn’t fully constructed yet, hence at a place where hashCode() can’t be invoked.

If you haven’t considered these gaps in your idea, you shouldn’t start using Instrumentation to alter the caller’s byte codes. It’s very unlikely that you will produce correct code. Even at places where an instance exist at the call cites, that instance doesn’t need to be available, nor does hash code calculation. What if you method get invoked from another object’s hashCode method?

Besides practical obstacles, the big question is, why do you think you need the “callers” hash code? What ever you intend to do with it, it can’t be right. Think of the following code:

public class Caller {
    public void aMethod() {
        Callee calleeObj = new Callee();
        new Thread(calleeObj::aSpecificMethod).start();
    }
}

Whose hash code are you interested in? Of the instance of the anonymous class generated at runtime? Of the Thread instance invoking the run method of that anonymous class? Or of the Caller instance which won’t be on the call stack at all, when your method get invoked?

Holger
  • 285,553
  • 42
  • 434
  • 765
  • Yeap. After trying some techniques, I also agreed with your opinion. This starts from my curiosity to know the runtime structure of a Java program and it is closely connected to Software Architecture theory. But anyway, at this point, I totally agree with you. Thanks for the explanation. – byron1st May 26 '15 at 10:01
0

You have to pass either the calling object or its hash code as a parameter to the method.

user207421
  • 305,947
  • 44
  • 307
  • 483
  • Yeap. I agree. It seems there is no way using Javassist. I should consider other ways including ASM. – byron1st May 26 '15 at 01:45