9

There's a library which calls my method with a few arguments. I'd like to receive another argument, but the library doesn't provide it to the method it calls.

By decompiling the library, I can see that it has the argument, and it's assigned to an instance variable (not private, but not public either.) I know I can get at the variable using reflection if I have the instance, but I don't have the instance, either.

Is there a way I can get at the instance? SecurityManager has getClassContext(), but that just gives me the class of the instance - I want the instance itself.

As a quick example of what I want:

public class A {
    int b;
    public A(int b, int c) {
        this.b = b;
        D(c);
    }
}

public class D {
    public D(int c) {
        // Somehow I want to get at the calling instance of A's b from here,
        // and A belongs to a library which I didn't write.
    }
}

Alternatively... I do know that b was used as an argument on the callstack. So if someone knows how I could access the b which was passed into A's constructor, that would be acceptable.

If neither of these are doable... I can decompile A and compile it the way I want, and then I'd either need to do some classloading wizardry or I'd have to modify the contents of the jar. Neither of those sound desirable, so I'm hopeful someone knows how to either access the instance of A or the argument b from the call stack.

ArtOfWarfare
  • 20,617
  • 19
  • 137
  • 193
  • 2
    If "b" doesnt have a getter, you are not supposed to get it... or that is a horrible library. You could try to serialize the object into a readable string (for example Json using Gson or other libraries) but I am not sure if it will give you the private fields of objects in compiled libraries. – Wietlol Mar 28 '17 at 14:42
  • @Wietlol - If `b` had a getter, it would make no difference here. The problem is I need to find out how to get the instance of `A` which is constructing `D`. – ArtOfWarfare Mar 28 '17 at 14:50
  • Ah, I see. By simple terms, that would be impossible. However, if you can keep track of which object of "A" is created, you maybe could put it in a static variable. However, in this case, that might only be possible by overriding A – Wietlol Mar 28 '17 at 14:56
  • 1
    Why do you want to get the instance of `A` anyway? – MC Emperor Mar 28 '17 at 15:02
  • @MCEmperor - So I can get `b` from it. Okay, so in the actual scenario, the library that I'm using wants me to provide a class with methods to encrypt and decrypt passwords. All it passes in is the encrypted or decrypted string, though. I'd like to strengthen this by including a randomly generated per-user salt. So I need to get at the username, but the library doesn't provide that. I've decompiled the library and know that it has the username, but it doesn't pass that to my method - it only provides the one string. – ArtOfWarfare Mar 28 '17 at 15:37
  • As an aside, I'm surprised at how well this question has been received. It seems like normally when a question is asked with a lot of people responding with "you can't", there's normally a lot of down voting that accompanies it. I hesitated just posting this question because I expected a flood of downvotes. – ArtOfWarfare Mar 28 '17 at 15:40
  • How do you enforce that there is an instance of `A` calling your method? Or that there is a “calling object” at all? Your method could be invoked from a `static` method, for example. – Holger Nov 20 '17 at 15:31
  • @Holger - Why do I need to enforce anything? I was just looking for a reflection method that would return the calling instance. Such a method would have a return type of `Object`, and return `null` (or maybe throw an exception, or return the `Class` object... many options here) if it was statically called. That'd obviously be up to me, as the person calling the reflection method, to decide how to handle. – ArtOfWarfare Nov 20 '17 at 17:28
  • `static` methods are just an example of inherit flaws in the concept of a “caller object”. Ironically, your question provides another example, having your method being called from a constructor, so the “caller object” would be an incomplete object. There are so many things wrong with this idea, semantically and technically, making it very unlikely that the JRE developers will ever consider such a feature. – Holger Nov 20 '17 at 17:59
  • Are the classes final? When not simply them override them. – akop Apr 02 '23 at 15:20

3 Answers3

2

With the help of code you provided, i could think of writing an aspect i mean use aop and try using joinpoint to get the arguments that are passed to constructor A()

Alekhya
  • 272
  • 1
  • 7
  • Could you expand on this? Can this work without me having to modify `A`? – ArtOfWarfare Mar 28 '17 at 15:39
  • you can use this post's answer as a reference http://stackoverflow.com/questions/17338788/aspectj-pointcut-on-constructor-object . you dont need to modify A for this. – Alekhya Mar 28 '17 at 15:43
1

Somehow I want to get at the calling instance of A's b from here

Short answer: you can't.

Long answer: you can get it if you either run it on a debugger, or your own custom JVM.

Yet another solution: use aspect-oriented programming with a framwork like AspectJ

m0skit0
  • 25,268
  • 11
  • 79
  • 127
  • I believe this will be running on OpenJVM... does that change anything? I don't think I can change that. The JVM does have a copy of byteman running with it... I know I've used byteman previously to extract variables and put them into log files... is it possible to also use it to access the calling instance with it? – ArtOfWarfare Mar 28 '17 at 15:42
  • Why would you put in log files? I would directly use a debugger inside a IDE, it is way more convenient. I've added a third option which you might find interesting. – m0skit0 Mar 28 '17 at 16:30
0

You cannot do that. See this post for more details.

There is no such thing as an 'owner', so you cannot get the calling instance, unless an explicit reference to the parent is specified:

class A {
    int b;
    A(int b, int c) {
        this.b = b;
        new D(this, c);
    }
}

class D {
    D(A a, int c) {
        ...
    }
}

It seems that either according to the library your are not supposed to get such instance, or it is poorly designed.

Community
  • 1
  • 1
MC Emperor
  • 22,334
  • 15
  • 80
  • 130