13

I would like to write a code internal to my method that print which method/class has invoked it.

(My assumption is that I can't change anything but my method..)

How about other programming languages?

EDIT: Thanks guys, how about JavaScript? python? C++?

DuduAlul
  • 6,313
  • 7
  • 39
  • 63
  • 2
    I am repeatedly astounded by what weird hacks some people "would like to write". No offense meant. –  Aug 12 '10 at 13:48
  • 3
    @del This isn't really a hack. It's basically a form of logging that can be really helpful. – jjnguy Aug 12 '10 at 13:58
  • possible duplicate of [In Java, how do i find the caller of a method using stacktrace or reflection?](http://stackoverflow.com/questions/421280/in-java-how-do-i-find-the-caller-of-a-method-using-stacktrace-or-reflection) – Adam Paynter Aug 12 '10 at 15:06
  • 1
    Whoops, ignore my "possible duplicate". Didn't notice the other languages. :) – Adam Paynter Aug 12 '10 at 15:22
  • @adam you can easily compensate with a vote up ;-) haha – DuduAlul Aug 12 '10 at 15:42
  • 1
    Kind of needs to be language specific, unless asking about the subjective philosophy of providing this sort of facility. – Tom Hawtin - tackline Aug 12 '10 at 21:40

8 Answers8

20

This is specific to Java.

You can use Thread.currentThread().getStackTrace(). This will return an array of StackTraceElements.

The 2nd element in the array will be the calling method.

Example:

public void methodThatPrintsCaller() {
    StackTraceElement elem = Thread.currentThread.getStackTrace()[2];
    System.out.println(elem);

    // rest of you code
}
jjnguy
  • 136,852
  • 53
  • 295
  • 323
4

If all you want to do is print out the stack trace and go hunting for the class, use

Thread.dumpStack();

See the API doc.

Jay R.
  • 31,911
  • 17
  • 52
  • 61
4

Justin has the general case down; I wanted to mention two special cases demonstrated by this snippit:

import java.util.Comparator;

public class WhoCalledMe {

    public static void main(String[] args) {
        ((Comparator)(new SomeReifiedGeneric())).compare(null, null);
        new WhoCalledMe().new SomeInnerClass().someInnerMethod();
    }

    public static StackTraceElement getCaller() {
        //since it's a library function we use 3 instead of 2 to ignore ourself
        return Thread.currentThread().getStackTrace()[3];
    }

    private void somePrivateMethod() {
        System.out.println("somePrivateMethod() called by: " + WhoCalledMe.getCaller());
    }

    private class SomeInnerClass {
        public void someInnerMethod() {
            somePrivateMethod();
        }
    }
}

class SomeReifiedGeneric implements Comparator<SomeReifiedGeneric> {
    public int compare(SomeReifiedGeneric o1, SomeReifiedGeneric o2) {
        System.out.println("SomeRefiedGeneric.compare() called by: " + WhoCalledMe.getCaller());
        return 0;
    }
}

This prints:

SomeRefiedGeneric.compare() called by: SomeReifiedGeneric.compare(WhoCalledMe.java:1)
somePrivateMethod() called by: WhoCalledMe.access$0(WhoCalledMe.java:14)

Even though the first is called "directly" from main() and the second from SomeInnerClass.someInnerMethod(). These are two cases where there is a transparent call made in between the two methods.

  • In the first case, this is because we are calling the bridge method to a generic method, added by the compiler to ensure SomeReifiedGeneric can be used as a raw type.
  • In the second case, it is because we are calling a private member of WhoCalledMe from an inner class. To accomplish this, the compiler adds a synthetic method as a go-between to override the visibility problems.
Mark Peters
  • 80,126
  • 17
  • 159
  • 190
3

the sequence of method calls is located in stack. this is how you get the stack: Get current stack trace in Java then get previous item.

Community
  • 1
  • 1
Andrey
  • 59,039
  • 12
  • 119
  • 163
1

Since you asked about other languages, Tcl gives you a command (info level) that lets you examine the call stack. For example, [info level -1] returns the caller of the current procedure, as well as the arguments used to call the current procedure.

Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685
1

In Python you use the inspect module. Getting the function's name and file name is easy, as you see in the example below.

Getting the function itself is more work. I think you could use the __import__ function to import the caller's module. However you must somehow convert the filename to a valid module name.

import inspect

def find_caller():
    caller_frame = inspect.currentframe().f_back
    print "Called by function:", caller_frame.f_code.co_name
    print "In file           :", caller_frame.f_code.co_filename
    #Alternative, probably more portable way
    #print inspect.getframeinfo(caller_frame)

def foo():
    find_caller()

foo()
Eike
  • 2,205
  • 17
  • 10
0

Yes, it is possible.

Have a look at Thread.getStackTrace()

Tim
  • 6,406
  • 22
  • 34
0

In Python, you should use the traceback or inspect modules. These will modules will shield you from the implementation details of the interpreter, which can differ even today (e.g. IronPython, Jython) and may change even more in the future. The way these modules do it under the standard Python interpreter today, however, is with sys._getframe(). In particular, sys._getframe(1).f_code.co_name provides the information you want.

kindall
  • 178,883
  • 35
  • 278
  • 309