tags:

views:

339

answers:

7

how can i find out which class/method has called the actual method?

A: 

You can print a stack trace to do this.

If you want to do this dynamically, I'm not really sure if this is possible (aside from printing and parsing a stack trace dynamically).

samoz
+8  A: 

You could try to create an exception to get its stacktrace.

Throwable t = new Throwable();
StackTraceElement[] stackTraceElements = t.getStackTrace();

Now stackTraceElement[0] contains the caller of the current method.

But beware (from Throwable.getStackTrace()):

Some virtual machines may, under some circumstances, omit one or more stack frames from the stack trace. In the extreme case, a virtual machine that has no stack trace information concerning this throwable is permitted to return a zero-length array from this method. Generally speaking, the array returned by this method will contain one element for every frame that would be printed by printStackTrace.

Bombe
Thread.currentThread().getStackTrace() will do the dirty work of creating a Throwable for you.
Michael Myers
And obtaining the stack trace in Java is an expensive operation. So don't use it every here and there.
mkoeller
this did exactly what i expected, thanksalot.
machine
Thread.getStackTrace() doesn't actually create a Throwable, does it? It just invokes the native method "dumpThreads" to get the stack info. Also, this is a bad solution.
matt b
@matt b - in earlier versions of the sun JVM, it used to.
Yishai
stackTraceElement[0] contains the class of the current method. stackTraceElement[1] would contain the caller of the current method.
Yishai
@matt b: If it is called on the current thread, it creates an Exception and returns its stack trace. Otherwise, it goes to the native method.
Michael Myers
A: 

You could use a debugger, or a profiler. Netbeans has both, but a lot of other options exists.

Else, if you can modify the code you can throw a new exception() and have a stacktrace printed in the console.

HeDinges
A: 

Is this for debugging, or to provide some functionality?

Visage
why -1? follow up questions are banned? I'll give it a +1 to make up for the loss :-)
Hemal Pandya
+4  A: 

Here's one way that I've used:

StackTraceElement element=Thread.currentThread().getStackTrace()[3];
String className=element.getClassName();
String methodName=element.getMethodName();

[3] is hardcoded because:

[0] is Thread.dumpThreads()

[1] is Thread.getStackTrace()

[2] is the current method

[3] is the one before the current method

Peter Dolberg
That would seem to have the potential to break if Thread.getStackTrace changes its internal implementation. A more robust way would be to iterate over the elements until you get your class name and then get the class name of the element after that one.
Yishai
True, but I only used the code in Eclipse conditional breakpoints. I never considered that someone would use this code as part of any production code. It is just a debugging trick.
Peter Dolberg
A: 

To echo and elaborate on matt b and yishai's comments:

If you are doing this because you are writing a logger or maintaining trace information or some such, okay, cool. I've used stack traces in production code exactly once, and even that was really a debugging issue: We had a problem with database connections not being properly closed, so I modified the "get database connection" function to save the identity of the caller, and then had a periodic sweep to look for dead connections and see where they had been created.

Java's built-in logging function does stack traces so it can write who called the logger to the log file. I worry about the overhead of this as I understand that stack traces are expensive, but whatever.

But if you're doing this because your function is going to behave differently depending on where it was called from, like "if called from class X update customer data else if called from class Y update employee data" or something like that: Really really bad idea. Pass a parameter or write separate functions.

Jay
+1  A: 

A faster but non-portable solution is to use the following. It does not create a stack trace and just gives you the information you need. However, not all JVMs will have this and future version of Java might not either.

Class callerClass = sun.reflect.Reflection.getCallerClass(2);
Peter Lawrey
Indeed it works like a charm...and once you started with SUN implementation it's highly improbable that you will move on a different implementation...at least don't use it if you're writing a library...for an application is safe.
adrian.tarau
It is possible to write code which calls this methods if it available but calls the generic approach if it not. ;)
Peter Lawrey