533

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

Kedar Mhaswade
  • 4,535
  • 2
  • 25
  • 34
Omar Kooheji
  • 54,530
  • 68
  • 182
  • 238
  • 1
    I think that now (since Java 9) the accepted answer should be the one with `StackWalker`. The answer you accepted long time ago is now obsolete. – Honza Zidek Jun 14 '23 at 16:22
  • See the modern [`java.lang.StackWalker`](https://docs.oracle.com/javase/10/docs/api/java/lang/StackWalker.html) solution in [this Answer](https://stackoverflow.com/a/52335318/642706). – Basil Bourque Jul 23 '23 at 17:49

23 Answers23

360

Technically this will work...

String name = new Object(){}.getClass().getEnclosingMethod().getName();

However, a new anonymous inner class will be created during compile time (e.g. YourClass$1.class). So this will create a .class file for each method that deploys this trick. Additionally, an otherwise unused object instance is created on each invocation during runtime. So this may be an acceptable debug trick, but it does come with significant overhead.

An advantage of this trick is that getEnclosingMethod() returns java.lang.reflect.Method which can be used to retrieve all other information of the method including annotations and parameter names. This makes it possible to distinguish between specific methods with the same name (method overload).

Note that according to the JavaDoc of getEnclosingMethod() this trick should not throw a SecurityException as inner classes should be loaded using the same class loader. So there is no need to check the access conditions even if a security manager is present.

Please be aware: It is required to use getEnclosingConstructor() for constructors. During blocks outside of (named) methods, getEnclosingMethod() returns null.

pocketrocket
  • 365
  • 2
  • 8
Devin
  • 3,601
  • 1
  • 14
  • 2
  • Please comment if this is supported across all JVMs and that no such limitation similar to the omission of Stacktrace, exists – Drupad Panchal Dec 13 '11 at 16:00
  • 10
    This won't give you currently executing method. This will give you that method in which an anonymous/local class is defined. - http://docs.oracle.com/javase/6/docs/api/java/lang/Class.html#getEnclosingMethod() – shrini1000 May 04 '12 at 10:52
  • 7
    class Local {}; String name = Local.class.getEnclosingMethod().getName(); – alexsmail Mar 13 '13 at 05:16
  • 26
    @shrini1000 the idea is to use this snippet where the information is needed, and not put it in a library routine. – Thorbjørn Ravn Andersen Apr 15 '13 at 08:54
  • @Devin I am seeing that this also using native API like throwable. So How fast it is compared to other methods like StackTrace ..? – Kanagavelu Sugumar Nov 06 '13 at 13:35
  • 3
    Will this create an anonymous inner class during compile time even if you put this code in a catch block? – Adam Jensen Aug 19 '14 at 01:28
  • @AdamJensen, the class will be created/compiled at compile time, but instances will only be created if executed in the catch block. – Brett Okken Feb 17 '15 at 02:19
  • 4
    Thanks for the tips ! Instead of creating a new object, just use this.getClass().getEnclosingMethod().getName(); – Lilo Mar 27 '15 at 13:36
  • 4
    @Lilo incorrect. `getEnclosingMethod` gets the name of the method where the class is defined. `this.getClass()` won't help you at all. @wutzebaer why would you even need to? You have access to them already. – Hazel T Sep 20 '17 at 16:25
  • This method will raise a SonarLint issue Objects should not be created only to "getClass" – Yu Tian Toby Dec 27 '21 at 14:29
  • 1
    @YuTianToby [this comment](https://stackoverflow.com/questions/442747/getting-the-name-of-the-currently-executing-method#comment21732320_5891326) already provided an alternative which should not raise the issue. – Holger May 17 '23 at 09:02
202

Thread.currentThread().getStackTrace() will usually contain the method you’re calling it from but there are pitfalls (see Javadoc):

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 thread is permitted to return a zero-length array from this method.

randers
  • 5,031
  • 5
  • 37
  • 64
Bombe
  • 81,643
  • 20
  • 123
  • 127
  • 7
    Is this same pitfall true for stack traces in exceptions? – Nate Parsons Mar 03 '09 at 19:15
  • 8
    Yes, it is. The documentation for [Throwable](http://download.oracle.com/javase/1.5.0/docs/api/java/lang/Throwable.html).[getStackTrace()](http://download.oracle.com/javase/1.5.0/docs/api/java/lang/Throwable.html#getStackTrace(%29) contains the exact same paragraph. – Bombe Nov 11 '11 at 16:50
  • 4
    The underlying thing is that the JVM is not _required_ to be able to provide a stacktrace, but that a lot of work has gone into making HotSpot very reliable. You need to know, though, in case you want your code to not rely on the behavior of a specific JVM. – Thorbjørn Ravn Andersen Apr 15 '13 at 08:53
  • Alexsmail's version below does not create a stack trace and gives you access to the actual method object, not just the name (so you can find out return type too). I haven't bench marked but I suspect his method is much faster too since stack traces tend to be expensive. – Gus Jul 06 '13 at 21:48
142

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.

Community
  • 1
  • 1
VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • 2
    It only says "main" for me. :-/ – Prof. Falken May 25 '11 at 12:50
  • @Amigable: did you try to print the all `StackTraceElement` array for debugging purpose and to see if 'main' is actually the right method? – VonC May 25 '11 at 14:28
  • 7
    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. See also [@virgo47's answer](http://stackoverflow.com/a/8592871/505893). – bluish Dec 28 '11 at 13:15
  • 2
    @bluish: good point. I have included your comment and a reference to virgo47's answer in mine. – VonC Dec 28 '11 at 16:01
  • @VonC Is this implementation really correct? depth here must be ste.length + 1 for that to give current method. Should it not be ste[depth + 1] if we are to allow depth = 0 ? – mjs Mar 29 '20 at 15:35
  • @VonC Ok, thank you. Any reason why you do not edit your answer instead? Is it right in some cases? – mjs Mar 29 '20 at 18:39
  • @VonC Wait, are you saying that the JVM has modified the implementation and order of stacktraces in latter JDK versions? Initially I felt my memory also said stacktraces were pushed to. Now they are shifted. Wierd if that is true. – mjs Mar 29 '20 at 18:40
  • @mmm I am just saying I don't remember my exact environment when I wrote this. But I did acknowledge other answers as being more accurate. – VonC Mar 29 '20 at 18:57
92

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. :-)

virgo47
  • 2,283
  • 24
  • 30
  • 2
    This is still subtly vendor dependent. The JVM is not required to deliver reliable data for this code. – Thorbjørn Ravn Andersen Apr 15 '13 at 08:56
  • 7
    Per the JVM spec the JVM is not required to provide full stack traces (optimization, inlining and all that) and you've already discovered that your heuristic changed between Oracle Java 5 and Oracle Java 6. There is nothing guaranteeing that any other JVM will behave as you expect in your code, so you are subtly relying on vendor specific behavior. Which is perfectly fine, as long as you are aware of that, but if - for instance - you need to deploy on an IBM JVM (which we must) or on a Zing instance you may have to revisit your heuristic. – Thorbjørn Ravn Andersen Apr 16 '13 at 14:22
  • 1
    This seems the most robust of all the options presented here, dependencies notwithstanding. – Ian Mar 04 '18 at 01:41
49

Both of these options work for me with Java:

new Object(){}.getClass().getEnclosingMethod().getName()

Or:

Thread.currentThread().getStackTrace()[1].getMethodName()
Charlie S
  • 4,366
  • 6
  • 59
  • 97
48
 public class SomeClass {
   public void foo(){
      class Local {};
      String name = Local.class.getEnclosingMethod().getName();
   }
 }

name will have value foo.

alexsmail
  • 5,661
  • 7
  • 37
  • 57
  • 6
    Local.class.getEnclosingMethod() was null. jdk1.6.0_31, play 1.2.5 – eigil Nov 29 '13 at 15:33
  • @eigil that's interesting but without more info it is hard to tell what went "wrong" or when we should expect `null` – Maarten Bodewes Apr 15 '14 at 10:07
  • This is the same trick as [this answer](http://stackoverflow.com/a/5891326/589259). It has the advantage that it does not create a spurious object instance, it has the disadvantage that it requires a class declaration which cannot be inlined in the statement (i.e. normally it requires an additional line of code). – Maarten Bodewes Apr 15 '14 at 10:25
  • @eigil did you define the class within a class (example SomeClass), or within a method (example foo)? I found that defining a subclass without being wrapped in a method - or in a constructor - will cause getEnclosingMethod() to return null. – D.N. Mar 10 '15 at 17:22
  • Pretty sure I did exactly as described in this answer. I think it's something strange with playframework. Tested in 'normal' java without any problem. – eigil Mar 26 '15 at 11:24
40

java.lang.StackWalker, Java 9+

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.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
Radiodef
  • 37,180
  • 14
  • 90
  • 125
34

The fastest way I found is that:

import java.lang.reflect.Method;

public class TraceHelper {
    // save it static to have it available on every call
    private static Method m;

    static {
        try {
            m = Throwable.class.getDeclaredMethod("getStackTraceElement",
                    int.class);
            m.setAccessible(true);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static String getMethodName(final int depth) {
        try {
            StackTraceElement element = (StackTraceElement) m.invoke(
                    new Throwable(), depth + 1);
            return element.getMethodName();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}

It accesses the native method getStackTraceElement(int depth) directly. And stores the accessible Method in a static variable.

  • 3
    Fastest as in performance wise? Any micro-benchmark to support the claim? – Ibrahim Arief Aug 24 '12 at 09:27
  • 10
    +1. Using a simple timed loop on 1.6, 1,000,000 iterations using this method took 1219ms, while using `new Throwable().getStackTrace()` took 5614ms. – ach Jan 25 '13 at 17:14
  • 1
    m.setAccessible(true); should be surrounded by AccessController.doPrivileged. Something to consider, not a hard rule I would say – avanderw Jan 23 '14 at 09:47
  • 6
    Tested in 2016 and this continues to be the fastest. Like @ach I used 1M iterations. 1.7_79: 1.6s vs 15.2s 1.8_74: 1.8s vs 16.0s. FWIW my benchmark ste array's length==23 but this method stays fast regardless of stack depth. – Ryan Jun 30 '16 at 17:54
  • This doesn't work in Java 11: there is no method `Throwable.getStackTraceElement(int)` – Dennie Feb 22 '23 at 10:17
  • 1
    @Dennie even if there was that method, `setAccessible(true)` would fail nowadays. – Holger May 17 '23 at 09:18
25

Use the following Code :

    StackTraceElement[] stacktrace = Thread.currentThread().getStackTrace();
    StackTraceElement e = stacktrace[1];//coz 0th will be getStackTrace so 1st
    String methodName = e.getMethodName();
    System.out.println(methodName);
Sumit Singh
  • 15,743
  • 6
  • 59
  • 89
20
public static String getCurrentMethodName() {
        return Thread.currentThread().getStackTrace()[2].getClassName() + "." + Thread.currentThread().getStackTrace()[2].getMethodName();
    }
Micha Wiedenmann
  • 19,979
  • 21
  • 92
  • 137
Jay
  • 671
  • 9
  • 10
  • Yes, by far the best... turn it into a method and get the third ([2]) frame (or whatever it's called) in the trace. – mike rodent Oct 23 '16 at 10:28
  • 1
    Don’t repeat yourself. Especially when the repeated expression is an extremely expensive one, like `Thread.currentThread().getStackTrace()`. That’s what local variables are for, to store the result of an evaluation so you can use the result multiple times instead of repeating the evaluation. – Holger May 17 '23 at 09:13
14

This is an expansion on virgo47's answer (above).

It provides some static methods to get the current and invoking class / method names.

/* Utility class: Getting the name of the current executing method 
 * https://stackoverflow.com/questions/442747/getting-the-name-of-the-current-executing-method
 * 
 * Provides: 
 * 
 *      getCurrentClassName()
 *      getCurrentMethodName()
 *      getCurrentFileName()
 * 
 *      getInvokingClassName()
 *      getInvokingMethodName()
 *      getInvokingFileName()
 *
 * Nb. Using StackTrace's to get this info is expensive. There are more optimised ways to obtain
 * method names. See other stackoverflow posts eg. https://stackoverflow.com/questions/421280/in-java-how-do-i-find-the-caller-of-a-method-using-stacktrace-or-reflection/2924426#2924426
 *
 * 29/09/2012 (lem) - added methods to return (1) fully qualified names and (2) invoking class/method names
 */
package com.stackoverflow.util;

public class StackTraceInfo
{
    /* (Lifted from virgo47's stackoverflow answer) */
    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(StackTraceInfo.class.getName()))
            {
                break;
            }
        }
        CLIENT_CODE_STACK_INDEX = i;
    }

    public static String getCurrentMethodName()
    {
        return getCurrentMethodName(1);     // making additional overloaded method call requires +1 offset
    }

    private static String getCurrentMethodName(int offset)
    {
        return Thread.currentThread().getStackTrace()[CLIENT_CODE_STACK_INDEX + offset].getMethodName();
    }

    public static String getCurrentClassName()
    {
        return getCurrentClassName(1);      // making additional overloaded method call requires +1 offset
    }

    private static String getCurrentClassName(int offset)
    {
    return Thread.currentThread().getStackTrace()[CLIENT_CODE_STACK_INDEX + offset].getClassName();
    }

    public static String getCurrentFileName()
    {
        return getCurrentFileName(1);     // making additional overloaded method call requires +1 offset
    }

    private static String getCurrentFileName(int offset)
    {
        String filename = Thread.currentThread().getStackTrace()[CLIENT_CODE_STACK_INDEX + offset].getFileName();
        int lineNumber = Thread.currentThread().getStackTrace()[CLIENT_CODE_STACK_INDEX + offset].getLineNumber();

        return filename + ":" + lineNumber;
    }

    public static String getInvokingMethodName()
    {
        return getInvokingMethodName(2); 
    }

    private static String getInvokingMethodName(int offset)
    {
        return getCurrentMethodName(offset + 1);    // re-uses getCurrentMethodName() with desired index
    }

    public static String getInvokingClassName()
    {
        return getInvokingClassName(2); 
    }

    private static String getInvokingClassName(int offset)
    {
        return getCurrentClassName(offset + 1);     // re-uses getCurrentClassName() with desired index
    }

    public static String getInvokingFileName()
    {
        return getInvokingFileName(2); 
    }

    private static String getInvokingFileName(int offset)
    {
        return getCurrentFileName(offset + 1);     // re-uses getCurrentFileName() with desired index
    }

    public static String getCurrentMethodNameFqn()
    {
        return getCurrentMethodNameFqn(1);
    }

    private static String getCurrentMethodNameFqn(int offset)
    {
        String currentClassName = getCurrentClassName(offset + 1);
        String currentMethodName = getCurrentMethodName(offset + 1);

        return currentClassName + "." + currentMethodName ;
    }

    public static String getCurrentFileNameFqn()
    {
        String CurrentMethodNameFqn = getCurrentMethodNameFqn(1);
        String currentFileName = getCurrentFileName(1);

        return CurrentMethodNameFqn + "(" + currentFileName + ")";
    }

    public static String getInvokingMethodNameFqn()
    {
        return getInvokingMethodNameFqn(2);
    }

    private static String getInvokingMethodNameFqn(int offset)
    {
        String invokingClassName = getInvokingClassName(offset + 1);
        String invokingMethodName = getInvokingMethodName(offset + 1);

        return invokingClassName + "." + invokingMethodName;
    }

    public static String getInvokingFileNameFqn()
    {
        String invokingMethodNameFqn = getInvokingMethodNameFqn(2);
        String invokingFileName = getInvokingFileName(2);

        return invokingMethodNameFqn + "(" + invokingFileName + ")";
    }
}
Community
  • 1
  • 1
mvanle
  • 1,847
  • 23
  • 19
12

To get the name of the method that called the current method you can use:

new Exception("is not thrown").getStackTrace()[1].getMethodName()

This works on my MacBook as well as on my Android phone

I also tried:

Thread.currentThread().getStackTrace()[1]

but Android will return "getStackTrace" I could fix this for Android with

Thread.currentThread().getStackTrace()[2]

but then I get the wrong answer on my MacBook

11

Util.java:

public static String getCurrentClassAndMethodNames() {
    final StackTraceElement e = Thread.currentThread().getStackTrace()[2];
    final String s = e.getClassName();
    return s.substring(s.lastIndexOf('.') + 1, s.length()) + "." + e.getMethodName();
}

SomeClass.java:

public class SomeClass {
    public static void main(String[] args) {
        System.out.println(Util.getCurrentClassAndMethodNames()); // output: SomeClass.main
    }
}
Maxple
  • 329
  • 4
  • 5
  • ````final StackTraceElement e = Thread.currentThread().getStackTrace()[2]; ```` works; ````e.getClassName();```` return the full class name and ````e.getMethodName()```` return the methon name. – Marks Nov 26 '15 at 12:05
  • 2
    ``getStackTrace()[2]`` is wrong, it has to be ``getStackTrace()[3]`` because: [0] dalvik.system.VMStack.getThreadStackTrace [1] java.lang.Thread.getStackTrace [2] Utils.getCurrentClassAndMethodNames [3] The function a() calling this one – PhilLab Jul 13 '17 at 16:59
5

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());
Jool
  • 1,706
  • 16
  • 14
4
String methodName =Thread.currentThread().getStackTrace()[1].getMethodName();
System.out.println("methodName = " + methodName);
Linus Caldwell
  • 10,908
  • 12
  • 46
  • 58
ran
  • 73
  • 1
3

I've got solution using this (In Android)

/**
 * @param className       fully qualified className
 *                        <br/>
 *                        <code>YourClassName.class.getName();</code>
 *                        <br/><br/>
 * @param classSimpleName simpleClassName
 *                        <br/>
 *                        <code>YourClassName.class.getSimpleName();</code>
 *                        <br/><br/>
 */
public static void getStackTrace(final String className, final String classSimpleName) {
    final StackTraceElement[] steArray = Thread.currentThread().getStackTrace();
    int index = 0;
    for (StackTraceElement ste : steArray) {
        if (ste.getClassName().equals(className)) {
            break;
        }
        index++;
    }
    if (index >= steArray.length) {
        // Little Hacky
        Log.w(classSimpleName, Arrays.toString(new String[]{steArray[3].getMethodName(), String.valueOf(steArray[3].getLineNumber())}));
    } else {
        // Legitimate
        Log.w(classSimpleName, Arrays.toString(new String[]{steArray[index].getMethodName(), String.valueOf(steArray[index].getLineNumber())}));
    }
}
Kasim Rangwala
  • 1,765
  • 2
  • 23
  • 44
3

I don't know what is the intention behind getting the currently executed method's name, but if that's just for debugging purpose, then logging frameworks like "logback" can help here. For example, in logback, all you need to do is to use the pattern "%M" in your logging configuration. However, this should be used with caution as this may degrade performance.

Community
  • 1
  • 1
James Selvakumar
  • 2,679
  • 1
  • 23
  • 28
3

Just in case the method which name you want to know is a junit test method, then you can use junit TestName rule: https://stackoverflow.com/a/1426730/3076107

Egl
  • 774
  • 7
  • 20
3

I use this code snippet with the latest Android Studio with the latest Java update. It can be called from any Activity, Fragment, etc.

public static void logPoint() {
    String[] splitPath = Thread.currentThread().getStackTrace()[3]
        .toString().split("\\.");

    Log.d("my-log", MessageFormat.format("{0} {1}.{2}",
        splitPath[splitPath.length - 3],
        splitPath[splitPath.length - 2],
        splitPath[splitPath.length - 1]
    ));
}

call it like this

logPoint();

output

... D/my-log: MainActivity onCreate[(MainActivity.java:44)]
fix
  • 1,425
  • 16
  • 27
1

Most answers here seems wrong.

    public static String getCurrentMethod() {
            return getCurrentMethod(1);
    }
    public static String getCurrentMethod(int skip) {
            return Thread.currentThread().getStackTrace()[1 + 1 + skip].getMethodName();
    }

Example:

    public static void main(String[] args) {
            aaa();
    }

    public static void aaa() {
            System.out.println("aaa  -> "  + getCurrentMethod( ) );
            System.out.println("aaa  -> "  + getCurrentMethod(0) );
            System.out.println("main -> "  + getCurrentMethod(1) );
    }

Outputs:

aaa  -> aaa
aaa  -> aaa
main -> main
mjs
  • 21,431
  • 31
  • 118
  • 200
  • 3
    Could you please clarify why do most answer seem wrong for you? There are many answers and I'm not that well-versed in Java to read all of them and to understand what's the difference between them and your answer. :( – Xobotun May 06 '20 at 14:35
  • 4
    @mmm Sorry, but I strongly disagree. I come here to learn and so do many others, I believe. I just cannot understand why do you think I don't deserve to know more on this subject. I want to make less mistakes in my code and to warn others, not to follow some cargo-cult. You could've at least clarified what Java version this code should be correct on. :( An answer below says there was a change in stacktrace between 1.5 and 1.6. Maybe you imply there's something like that in the upcoming Java 14, how can I know. Or different vendor may have. Sorry if I misinterpreted your answer as a rude one. – Xobotun May 10 '20 at 16:18
0

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);
}

Marco Sulla
  • 15,299
  • 14
  • 65
  • 100
0

Preferred Solution for Java 9 or above:

private static String getCurrentMethodName() {
  return StackWalker.getInstance()
    .walk(frames -> frames.skip(1).findFirst().map(StackWalker.StackFrame::getMethodName))
    .orElse("Anything");
}

StackWalker has a few advantages:

  • no need to create a dummy anonymous inner class instance, i.e., new Object().getClass() {}
  • no need to eagerly capture the whole stack trace, which can be costly

Read more in this article.

Saikat
  • 14,222
  • 20
  • 104
  • 125
-2
MethodHandles.lookup().lookupClass().getEnclosingMethod().getName();
Darren
  • 53
  • 2
  • 12
    Please edit with more information. Code-only and "try this" answers are discouraged, because they contain no searchable content, and don't explain why someone should "try this". – abarisone Sep 27 '16 at 14:31
  • 1
    Although this code may help to solve the problem, it doesn't explain _why_ and/or _how_ it answers the question. Providing this additional context would significantly improve its long-term educational value. Please [edit] your answer to add explanation, including what limitations and assumptions apply. – Toby Speight Sep 28 '16 at 08:27
  • 1
    Only for Java 7+, but concise way to get the method name. Still, remains the performance considerations of such a call. – Benj Oct 11 '16 at 12:29
  • 7
    `getEnclosingMethod()` throws a `NullPointerException` for me in Java 7. – Markus L Apr 07 '17 at 09:47
  • 2
    The java.lang.Class.getEnclosingMethod() returns a Method object representing the immediately enclosing method of the underlying class, if this Class object represents a local or anonymous class within a method, else returns null. – stove Apr 25 '18 at 07:21
  • What is the footprint of such a call ? – Benj Jul 27 '18 at 13:35
  • 1
    This answer isn't correct. `lookup().lookupClass()` returns the class of the current method, and `getEnclosingMethod()` returns the method which the current class is declared in, *if* the current class is a local class. See https://ideone.com/jfN5GW. In other words, given `void foo() { class Local { void bar() { System.out.println(lookup().lookupClass().getEnclosingMethod()); } } new Local().bar(); }`, the method `foo()` is printed (because it's the enclosing method of `Local`), but this question wants the method `bar()` (because it's the "currently executing" method). – Radiodef Sep 14 '18 at 15:57