Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Getting a reference to caller object

2,339 views
Skip to first unread message

puchacz

unread,
Nov 26, 2010, 3:38:25 PM11/26/10
to
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

Eric Sosman

unread,
Nov 26, 2010, 4:07:31 PM11/26/10
to
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
eso...@ieee-dot-org.invalid

Arne Vajhøj

unread,
Nov 26, 2010, 4:34:15 PM11/26/10
to
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

Message has been deleted

Mike Schilling

unread,
Nov 26, 2010, 9:21:13 PM11/26/10
to

"Eric Sosman" <eso...@ieee-dot-org.invalid> wrote in message
news:icp7kf$ri3$1...@news.eternal-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.

Lew

unread,
Nov 26, 2010, 10:46:39 PM11/26/10
to
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

puchacz

unread,
Nov 28, 2010, 11:52:26 AM11/28/10
to

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

Eric Sosman

unread,
Nov 28, 2010, 1:58:39 PM11/28/10
to
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
eso...@ieee-dot-org.invalid

Roedy Green

unread,
Nov 29, 2010, 12:54:26 PM11/29/10
to
On Fri, 26 Nov 2010 12:38:25 -0800 (PST), puchacz
<piotr...@gmail.com> 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.

Arne Vajhøj

unread,
Nov 29, 2010, 7:41:07 PM11/29/10
to
On 29-11-2010 12:54, Roedy Green wrote:
> On Fri, 26 Nov 2010 12:38:25 -0800 (PST), puchacz
> <piotr...@gmail.com> 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[i];
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

0 new messages