Getting the name of the currently executing method

前端 未结 22 2242
闹比i
闹比i 2020-11-22 03:33

Is there a way to get the name of the currently executing method in Java?

相关标签:
22条回答
  • 2020-11-22 04:12

    We used this code to mitigate potential variability in stack trace index - now just call methodName util:

    public class MethodNameTest {
        private static final int CLIENT_CODE_STACK_INDEX;
    
        static {
            // Finds out the index of "this code" in the returned stack trace - funny but it differs in JDK 1.5 and 1.6
            int i = 0;
            for (StackTraceElement ste : Thread.currentThread().getStackTrace()) {
                i++;
                if (ste.getClassName().equals(MethodNameTest.class.getName())) {
                    break;
                }
            }
            CLIENT_CODE_STACK_INDEX = i;
        }
    
        public static void main(String[] args) {
            System.out.println("methodName() = " + methodName());
            System.out.println("CLIENT_CODE_STACK_INDEX = " + CLIENT_CODE_STACK_INDEX);
        }
    
        public static String methodName() {
            return Thread.currentThread().getStackTrace()[CLIENT_CODE_STACK_INDEX].getMethodName();
        }
    }
    

    Seems overengineered, but we had some fixed number for JDK 1.5 and were a bit surprised it changed when we moved to JDK 1.6. Now it's the same in Java 6/7, but you just never know. It is not proof to changes in that index during runtime - but hopefully HotSpot doesn't do that bad. :-)

    0 讨论(0)
  • 2020-11-22 04:13

    This can be done using StackWalker since Java 9.

    public static String getCurrentMethodName() {
        return StackWalker.getInstance()
                          .walk(s -> s.skip(1).findFirst())
                          .get()
                          .getMethodName();
    }
    
    public static String getCallerMethodName() {
        return StackWalker.getInstance()
                          .walk(s -> s.skip(2).findFirst())
                          .get()
                          .getMethodName();
    }
    

    StackWalker is designed to be lazy, so it's likely to be more efficient than, say, Thread.getStackTrace which eagerly creates an array for the entire callstack. Also see the JEP for more information.

    0 讨论(0)
  • 2020-11-22 04:13

    An alternative method is to create, but not throw, an Exception, and use that object from which to get the stack trace data, since the enclosing method will typically be at index 0 - as long as the JVM stores that information, as others have mentioned above. This not the cheapest method, however.

    From Throwable.getStackTrace() (this has been the same since Java 5 at least):

    The zeroth element of the array (assuming the array's length is non-zero) represents the top of the stack, which is the last method invocation in the sequence. Typically, this is the point at which this throwable was created and thrown.

    The snippet below assumes the class is non-static (because of getClass()), but that's an aside.

    System.out.printf("Class %s.%s\n", getClass().getName(), new Exception("is not thrown").getStackTrace()[0].getMethodName());
    
    0 讨论(0)
  • 2020-11-22 04:14

    January 2009:
    A full code would be (to use with @Bombe's caveat in mind):

    /**
     * Get the method name for a depth in call stack. <br />
     * Utility function
     * @param depth depth in the call stack (0 means current method, 1 means call method, ...)
     * @return method name
     */
    public static String getMethodName(final int depth)
    {
      final StackTraceElement[] ste = Thread.currentThread().getStackTrace();
    
      //System. out.println(ste[ste.length-depth].getClassName()+"#"+ste[ste.length-depth].getMethodName());
      // return ste[ste.length - depth].getMethodName();  //Wrong, fails for depth = 0
      return ste[ste.length - 1 - depth].getMethodName(); //Thank you Tom Tresansky
    }
    

    More in this question.

    Update December 2011:

    bluish comments:

    I use JRE 6 and gives me incorrect method name.
    It works if I write ste[2 + depth].getMethodName().

    • 0 is getStackTrace(),
    • 1 is getMethodName(int depth) and
    • 2 is invoking method.

    virgo47's answer (upvoted) actually computes the right index to apply in order to get back the method name.

    0 讨论(0)
  • 2020-11-22 04:14
    public static String getCurrentMethodName() {
            return Thread.currentThread().getStackTrace()[2].getClassName() + "." + Thread.currentThread().getStackTrace()[2].getMethodName();
        }
    
    0 讨论(0)
  • 2020-11-22 04:14

    I rewritten a little the maklemenz's answer:

    private static Method m;
    
    static {
        try {
            m = Throwable.class.getDeclaredMethod(
                "getStackTraceElement",
                int.class
            );
        }
        catch (final NoSuchMethodException e) {
            throw new NoSuchMethodUncheckedException(e);
        }
        catch (final SecurityException e) {
            throw new SecurityUncheckedException(e);
        }
    }
    
    
    public static String getMethodName(int depth) {
        StackTraceElement element;
    
        final boolean accessible = m.isAccessible();
        m.setAccessible(true);
    
        try {
            element = (StackTraceElement) m.invoke(new Throwable(), 1 + depth);
        }
        catch (final IllegalAccessException e) {
            throw new IllegalAccessUncheckedException(e);
        }
        catch (final InvocationTargetException e) {
            throw new InvocationTargetUncheckedException(e);
        }
        finally {
            m.setAccessible(accessible);
        }
    
        return element.getMethodName();
    }
    
    public static String getMethodName() {
        return getMethodName(1);
    }
    
    
    0 讨论(0)
提交回复
热议问题