简体   繁体   中英

Java or any other language: Which method/class invoked mine?

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++?

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
}

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 .

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.

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.

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.

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

Yes, it is possible.

Have a look at Thread.getStackTrace()

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 (eg 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM