Getting a reference to caller object

Discussion in 'Java' started by puchacz, Nov 26, 2010.

  1. puchacz

    puchacz Guest

    Hi,

    Is it possible to get a reference to caller object (and recursively
    all the way up the call stack)? I know about Thread.dumpStack() that
    calls new Exception() internally and about sun.reflect.Reflection
    class, but you can only get information about classes, method names
    and lines - not reference to live objects that in turn can be
    inspected using reflection for all field values etc. I know in general
    it is probably possible, because this is what debuggers do when
    showing stack frame.

    What would it take to get this information? It does not have to be
    100% compatible with all versions of JDK. Anything in reflection
    internal packages? Or maybe there's a library that already does it? To
    what degree it is possible without (a) running the whole jvm in
    special mode - like debug mode and (b) without processing the whole
    program in AspectJ or Hibernate bytecode postprocessors style, and of
    course (c) without rewriting the source to pass around "this"
    everywhere?

    Cheers,
    Piotr
     
    puchacz, Nov 26, 2010
    #1
    1. Advertising

  2. puchacz

    Eric Sosman Guest

    On 11/26/2010 3:38 PM, puchacz wrote:
    > Hi,
    >
    > Is it possible to get a reference to caller object (and recursively
    > all the way up the call stack)? [...]


    Maybe. What do you mean by "caller object?" For example, in

    public class Piotr {
    public static void main(String[] unused) {
    System.out.println(hello());
    }
    private static String hello() {
    // What is the "caller object" here?
    return "Bonjour";
    }
    }

    > [...] I know in general
    > it is probably possible, because this is what debuggers do when
    > showing stack frame.


    The debuggers I have used will show the method associated with
    each stack frame, and the class the method belongs to, and the source
    code's line number (if it's available). I have not seen a debugger
    that shows anything I would term a "caller object," so again: What
    do you mean? More to the point, what problem are you trying to solve?

    --
    Eric Sosman
    lid
     
    Eric Sosman, Nov 26, 2010
    #2
    1. Advertising

  3. puchacz

    Arne Vajhøj Guest

    On 26-11-2010 15:38, puchacz wrote:
    > Is it possible to get a reference to caller object (and recursively
    > all the way up the call stack)? I know about Thread.dumpStack() that
    > calls new Exception() internally and about sun.reflect.Reflection
    > class, but you can only get information about classes, method names
    > and lines - not reference to live objects that in turn can be
    > inspected using reflection for all field values etc. I know in general
    > it is probably possible, because this is what debuggers do when
    > showing stack frame.


    I don't think you can.

    > What would it take to get this information? It does not have to be
    > 100% compatible with all versions of JDK. Anything in reflection
    > internal packages? Or maybe there's a library that already does it? To
    > what degree it is possible without (a) running the whole jvm in
    > special mode - like debug mode and (b) without processing the whole
    > program in AspectJ or Hibernate bytecode postprocessors style, and of
    > course (c) without rewriting the source to pass around "this"
    > everywhere?


    I think you need to redesign so that you don't need this feature.

    Arne
     
    Arne Vajhøj, Nov 26, 2010
    #3
  4. puchacz

    Stefan Ram Guest

    Eric Sosman <> writes:
    > public class Piotr {
    > public static void main(String[] unused) {
    > System.out.println(hello()); (...)
    > // What is the "caller object" here?


    The closest approximation to an answer to the above
    question might be »Piotr.class«.

    (But I do not know whether such an object is instanciated
    when the class »Piotr« is initialized or only when such
    an object is first needed.)
     
    Stefan Ram, Nov 26, 2010
    #4
  5. "Eric Sosman" <> wrote in message
    news:icp7kf$ri3$-september.org...
    > On 11/26/2010 3:38 PM, puchacz wrote:
    >> Hi,
    >>
    >> Is it possible to get a reference to caller object (and recursively
    >> all the way up the call stack)? [...]

    >
    > Maybe. What do you mean by "caller object?" For example, in
    >
    > public class Piotr {
    > public static void main(String[] unused) {
    > System.out.println(hello());
    > }
    > private static String hello() {
    > // What is the "caller object" here?
    > return "Bonjour";
    > }
    > }
    >
    >> [...] I know in general
    >> it is probably possible, because this is what debuggers do when
    >> showing stack frame.

    >
    > The debuggers I have used will show the method associated with
    > each stack frame, and the class the method belongs to, and the source
    > code's line number (if it's available).


    And the local variables for each frame, including "this" (if the frame has a
    this.) I think the last of these is what's being asked for.
     
    Mike Schilling, Nov 27, 2010
    #5
  6. puchacz

    Lew Guest

    Eric Sosman writes:
    >> public class Piotr {
    >> public static void main(String[] unused) {
    >> System.out.println(hello()); (...)
    >> // What is the "caller object" here?


    Stefan Ram wrote:
    > The closest approximation to an answer to the above
    > question might be »Piotr.class«.
    >
    > (But I do not know whether such an object is instanciated
    > when the class »Piotr« is initialized or only when such
    > an object is first needed.)


    The class object comes into existence when the class is loaded, but not all
    class initialization happens then. The 'class' attribute is an attribute of
    the class object, not the class object itself. The VM loader loads and
    initializes the class 'Piotr' and calls its 'main()', and thus 'Piotr',
    running 'main()', is the caller of 'hello()'.

    The class is loaded upon first reference to it or its members, but not
    necessarily initialized right then. For example, a reference to 'Piotr.class'
    will load 'Piotr' if it wasn't already, but not initialize it.

    The invocation of 'main()' will cause class initialization, so that will have
    happened before the call to 'hello()'.

    --
    Lew
     
    Lew, Nov 27, 2010
    #6
  7. puchacz

    puchacz Guest

    On Nov 27, 3:46 am, Lew <> wrote:
    > Eric Sosman writes:
    > >>        public class Piotr {
    > >>            public static void main(String[] unused) {
    > >>                System.out.println(hello());            (...)
    > >>                // What is the "caller object" here?

    > Stefan Ram wrote:
    > >    The closest approximation to an answer to the above
    > >    question might be »Piotr.class«.

    >
    > >    (But I do not know whether such an object is instanciated
    > >    when the class »Piotr« is initialized or only when such
    > >    an object is first needed.)

    >
    > The class object comes into existence when the class is loaded, but not all
    > class initialization happens then.  The 'class' attribute is an attribute of
    > the class object, not the class object itself.  The VM loader loads and
    > initializes the class 'Piotr' and calls its 'main()', and thus 'Piotr',
    > running 'main()', is the caller of 'hello()'.
    >
    > The class is loaded upon first reference to it or its members, but not
    > necessarily initialized right then.  For example, a reference to 'Piotr..class'
    > will load 'Piotr' if it wasn't already, but not initialize it.
    >
    > The invocation of 'main()' will cause class initialization, so that will have
    > happened before the call to 'hello()'.
    >
    > --
    > Lew




    Hi guys,

    Thanks, but this is not what I want; I would like something like the
    program below. Basically references to live objects, not class
    definition objects. It is for easier troubleshooting of an existing
    large production system, if something sets up a bad status, I would
    like to know what caused it, we have a lot of information in JMX
    already to click through, but not real stacks - and you cannot really
    debug a live production system.

    By debugger I mean debugger, like Eclipse debugger - you can see all
    stack frames, local variables in them, and "this" local to each stack
    frame, so you see values of fields in each object in stack frames,
    from your breakpoint location all the way up to top level Thread.run()
    or similar.

    Cheers,
    Piotr

    class A {
    int i, j;
    void a() {
    i = 1;
    j = 2;
    aa();
    }

    void aa() {
    B b = new B();
    b.b(this);
    }
    }

    class B {
    void b(Object o) {
    // assuming Magic.getStackFrame(thread, nextFrame - null means we are
    asking for the last frame in stack)

    // getting first from stack frame
    Frame frame1 = Magic.getStackFrame(Thread.currentThread(), null);

    // THIS IS WHAT I WANT TO RETRIEVE, FROM HERE
    assert(frame1.objectRef == o);
    assert(A.class.getDeclaredField("i").get(frame1.objectRef) == 1);
    assert(A.class.getDeclaredField("j").get(frame1.objectRef) == 2);
    // TO HERE

    // we were called from no arg method - this is retrieveable from
    // Thread.dumpStack() actually
    assert(frame1.method.equals(A.class.getMethod("aa", new Class[]
    {Object.class})));

    Frame frame2 = Magic.getStackFrame(Thread.currentThread(), frame1);
    assert(frame2.objectRef == frame1.objectRef); // the same object,
    also not retrievable using what I know
    assert(frame2.objectRef == o);
    assert(frame1.method.equals(A.class.getMethod("a", new Class[]{})));

    Frame frame3 = Magic.getStackFrame(Thread.currentThread(), frame2);
    assert(frame3.objectRef == null); // this method was called from
    static method
    assert(frame3.method.equals(C.getMethod("main"), new Class[]
    {String[].class}));

    Frame frame4 = Magic.getStackFrame(Thread.currentThread(), frame3);
    assert(frame4 == null); // it was top level frame

    // etc.
    }
    }

    class C {
    public static void main(String s[]) {
    new A().a();
    }
    }
     
    puchacz, Nov 28, 2010
    #7
  8. puchacz

    Eric Sosman Guest

    On 11/28/2010 11:52 AM, puchacz wrote:
    > [...]
    > Thanks, but this is not what I want; I would like something like the
    > program below. Basically references to live objects, not class
    > definition objects. It is for easier troubleshooting of an existing
    > large production system, if something sets up a bad status, I would
    > like to know what caused it, we have a lot of information in JMX
    > already to click through, but not real stacks - and you cannot really
    > debug a live production system.


    I don't think you'll get what you want, short of running the
    code under a debugger. Perhaps the java.lang.instrument package
    would help -- but using those facilities seems pretty close to (and
    as intrusive as) using a debugger to begin with.

    --
    Eric Sosman
    lid
     
    Eric Sosman, Nov 28, 2010
    #8
  9. puchacz

    Roedy Green Guest

    On Fri, 26 Nov 2010 12:38:25 -0800 (PST), puchacz
    <> wrote, quoted or indirectly quoted someone who
    said :

    >Is it possible to get a reference to caller object (and recursively
    >all the way up the call stack)?


    yes. You can all sorts of information.

    See http://mindprod.com/jgloss/trace.html
    for sample code.
    --
    Roedy Green Canadian Mind Products
    http://mindprod.com

    If you give your kitchen floor a quick steam mop every few days, you will find you never have to get out buckets and brushes for deep cleaning. Similary, if you keep your code tidy, refactoring as you go, you probably won't need major rewrites.
     
    Roedy Green, Nov 29, 2010
    #9
  10. puchacz

    Arne Vajhøj Guest

    On 29-11-2010 12:54, Roedy Green wrote:
    > On Fri, 26 Nov 2010 12:38:25 -0800 (PST), puchacz
    > <> wrote, quoted or indirectly quoted someone who
    > said :
    >> Is it possible to get a reference to caller object (and recursively
    >> all the way up the call stack)?

    >
    > yes. You can all sorts of information.
    >
    > See http://mindprod.com/jgloss/trace.html
    > for sample code.


    Two quick questions:

    1) what is an object?

    2) what of the code below

    Throwable t = new Throwable();
    StackTraceElement[] es = t.getStackTrace();
    for ( int i=0; i<es.length; i++ )
    {
    StackTraceElement e = es;
    System.out.println( " in class:" + e.getClassName()
    + " in source file:" + e.getFileName()
    + " in method:" + e.getMethodName()
    + " at line:" + e.getLineNumber()
    + " " + ( e.isNativeMethod() ? "native" : "" ) );
    }

    finds "caller object"?

    Arne
     
    Arne Vajhøj, Nov 30, 2010
    #10
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. opistobranchia
    Replies:
    1
    Views:
    347
    Larry I Smith
    Aug 14, 2005
  2. Michael Neumann

    Getting the binding of the caller

    Michael Neumann, Aug 17, 2004, in forum: Ruby
    Replies:
    9
    Views:
    200
    Michael Neumann
    Aug 18, 2004
  3. Peter Laurens
    Replies:
    11
    Views:
    201
    ara.t.howard
    Aug 3, 2007
  4. Xeno Campanoli
    Replies:
    2
    Views:
    82
    Xeno Campanoli
    Jun 30, 2009
  5. Mark
    Replies:
    2
    Views:
    411
Loading...

Share This Page