Java: How to get the caller function name

前端 未结 6 1161
情深已故
情深已故 2021-02-05 01:56

To fix a test case I need to identify whether the function is called from a particular caller function. I can\'t afford to add a boolean parameter because it would break the int

相关标签:
6条回答
  • 2021-02-05 02:29

    I tweaked the code that is being discussed here and customized it to get the invoking method. What the code does here is to iterate over the stack trace elements and as soon as it finds the name of the method being invoked, it gets the name of the previous method, which in turn will be the method that is invoking this method.

        private String method() {
        String methodName=null;
        StackTraceElement[] stacktrace = Thread.currentThread().getStackTrace();
        for (int i = 0; i < stacktrace.length; i++) {
            if(stacktrace[i].getMethodName().equals("method")) {
                methodName = stacktrace[i+1].getMethodName();
                break;
            }
        }
          return methodName;
    
    }
    
    0 讨论(0)
  • 2021-02-05 02:32

    You could try

    StackTraceElement[] stacktrace = Thread.currentThread().getStackTrace();
    StackTraceElement e = stacktrace[2];//maybe this number needs to be corrected
    String methodName = e.getMethodName();
    
    0 讨论(0)
  • 2021-02-05 02:43

    Here's a function I wrote to Log the function name of the function that calls it. It runs up the stack trace until it finds a function named logIt, then displays the next name. It's a dirty hack, so don't do it unless you're using it to debug.

    private static void logIt() {
        StackTraceElement[] stacktrace = Thread.currentThread().getStackTrace();
        boolean logged = false;
        boolean foundMe = false;
        for(int i=0; i<stacktrace.length; i++) {
            StackTraceElement e = stacktrace[i];
            String methodName = e.getMethodName();
            if (foundMe) {
                if (!methodName.startsWith("access$")) {
                    Log.i(TAG, String.format(Locale.US, "%s.%s", e.getClassName(), methodName));
                    logged = true;
                    break;
                }
            } else {
                if (methodName.equals("logIt")) {
                    foundMe = true;
                }
            }
        }
        if (!logged)
            Log.e(TAG, "unlogged call");
    }
    
    0 讨论(0)
  • 2021-02-05 02:45

    I have no idea why but in my shop the develop system differs from the test and production environments shifting position in the stack. I was forced to loop through the stack to find and get the calling method from the next element in the stack trace. A little clunkier but so far has been consistently returning the desired method. I use this as part of my error handling to identify where an exception was caught.

        List<String> list = new ArrayList<String>();
        StackTraceElement[] elements = Thread.currentThread().getStackTrace();
        for (int i = 0; i < Thread.currentThread().getStackTrace().length; i++) {
            System.out.println("Stack: "
                    + i
                    + " Class: "
                    + elements[i].getClassName()
                    + " Method: "
                    + elements[i].getMethodName());
            if (elements[i].getMethodName().equals("<init>")) {
                list.add(elements[i + 1].getClassName());
                list.add(elements[i + 1].getMethodName());
                 break;
            } // if
        } // for
    
    0 讨论(0)
  • 2021-02-05 02:49

    I sometimes want to make some outputs to the logcat. So I wrote a tiny class with some testing-methods:

    public class Common {
    
        // can be used as test-flag anywhere in the app (set to false, when release the app)
        public static boolean b_TEST_MODE = true;
    
        public static void echo(String message) {
            if (b_TEST_MODE) {
                StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
                // subtring(25) is to cut off app-name from output
                System.out.println(">>> " + stackTraceElements[3].toString().substring(25) + ": " + message);
            }
        }
    }
    

    now you can call it from anywhere in the app to get some infos:

    String sSQLQuery = "SELECT * FROM database WHERE id=23";
    Common.echo(sSQLQuery);
    

    The logcat prints out:

    >>> MainActivity.onCreate(MainActivity.java:46): SELECT * FROM dateabase WHERE id=23
    
    0 讨论(0)
  • 2021-02-05 02:56

    Another sample for android usage:

    //package your.package.name;
    import android.util.Log;
    /*
     File name: MyDebugLog.java
    */
    public class MyDebugLog {
        private static final int    index      = 4;     // <== Index in call stack array
        private static final String methodName = "Log"; // <== Name of method for public call
        private static String getCallerName() {
            String caller = "NONE";
            final StackTraceElement[] stacktrace = Thread.currentThread().getStackTrace();
            for (int i = 0; i < stacktrace.length; i++) {
                Log.e("Method ", "[" + i + "]" + stacktrace[i].getMethodName());
            }
            if (stacktrace.length >= index){
                caller = stacktrace[index].getMethodName();
            }
            return caller;
        }
    
        private static String getTag() {
            String tag = "NONE";
            final StackTraceElement[] stacktrace = Thread.currentThread().getStackTrace();
            for (int i = 0; i < stacktrace.length; i++) {
                Log.e("Method ", "[" + i + "]" + stacktrace[i].getMethodName());
                if (stacktrace[i].getMethodName().equals(methodName)) {
                    tag = "("+stacktrace[i + 1].getFileName() + ":" + stacktrace[i + 1].getLineNumber()+")";
                    return tag;
                }
            }
            return tag;
        }
    
        public static void Log(String message){
            Log.v(getTag(), getCallerName() + " " + message);
        }
    }
    

    Usage:

        @Override
        protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.sample_main);
                MyDebugLog.Log("XXXXX");
        }
    

    Output:

        V/(MainActivity.java:117): onCreate XXXXX
    

    Sample of arrays:

     getTag Sample of stacktace array:
    
        Method: [0]getThreadStackTrace
        Method: [1]getStackTrace
        Method: [2]getTag
        Method: [3]Log                 <== Method for external call
        ...
     getName Sample of stacktace array:
        Method: [0]getThreadStackTrace
        Method: [1]getStackTrace
        Method: [2]getCallerName
        Method: [3]Log
        Method: [4]onCreate            <== Our external method
        Method: [5]performCreate
        ...
    
    0 讨论(0)
提交回复
热议问题