1

I have been working on a small logging/debug library for my Java projects. I know there are many good ones already out there but I want to learn from doing one myself.

One method I want to have as part of this library is the ability to find out which method you are in at any one time, similar to __func__ in C++. Most of the time it'd be fine to just use the StackTrace to find this, since you often don't need more than the name (and/or declaring class) of the method, but I want to have the ability to get the method as an instance of the java.lang.reflect.Method

The easiest way of doing this is by simply doing

Method currentMethod = new Object() {}.getClass().getEnclosingMethod();

which will work just fine, but I can't figure out a way to do the same without creating that 'new Object() {}' within the method itself. Ideally I'd prefer if I could make a simple

Method currentMethod = _method();

to get the same result but with my current approach it'd just get me the Method-instance of _method itself.

Is there any known method to achieve this? If there isn't that's fine, but it'd be nice to have one.

EDIT: A lot of suggestions I receive, such as this post, provide mostly answers that provide you with the NAME of the method. It would be possible to use that (and the Class info gained in the same way) to find the Method, but only if the class in question has only one method with that name. Methods with the same name but different arguments cannot be identified with this!

Anju Maaka
  • 263
  • 1
  • 10
  • How do you expect you invoke `_method()` without using a reference (object) to call the function? – hfontanez Feb 10 '22 at 14:07
  • 1
    Does this answer your question? [Getting the name of the currently executing method](https://stackoverflow.com/questions/442747/getting-the-name-of-the-currently-executing-method) – Nexevis Feb 10 '22 at 14:10
  • @hfontanez Using "static import" on the class containing all these utility methods. Otherwise it'd be more like "DebugUtil._method()" instead. – Anju Maaka Feb 10 '22 at 14:26
  • You are still referencing "some class", don't you? – hfontanez Feb 10 '22 at 14:28
  • @Nexevis No, that is the method I'm currently using and it requires you to create that "new Object() {}" within the method you're currently inside. I want to be able to call a different, static, method that doesn't require any arguments. – Anju Maaka Feb 10 '22 at 14:28
  • @Anju Maaka There are many other answers in that link than just the top answer, not just the one you are currently using. – Nexevis Feb 10 '22 at 14:29
  • @hfontanez I suppose so? I'm not quite understanding what you're trying to say. Imagine you have one java class called UtilityMethods which contains a number of static methods. Any OTHER class can do a static import (or just a normal import) to use those methods. I want one of those methods to be able to return a Method instance that points to the method that called it – Anju Maaka Feb 10 '22 at 14:31
  • @Nexevis Yes, there are many other answers, but I've already looked through the site earlier and all answers seem to either not provide a java.lang.reflect.Method OR they require third party libraries (which I'm trying to avoid) – Anju Maaka Feb 10 '22 at 14:33
  • @hfontanez Simple you say? The whole question is about how your suggestion _does not work_ since if I did "create [my] own private method that [creates the new Object() {}] and call [that] method" then I would get a Method object that points to this 'private method' when I want it to point _to the method that CALLS this 'private method' instead_ – Anju Maaka Feb 10 '22 at 14:38
  • @AnjuMaaka are you sure about that? Run my answer – hfontanez Feb 10 '22 at 14:44
  • @hfontanez Already did. Received the _method Method, not the one that called it – Anju Maaka Feb 10 '22 at 14:48
  • So your question isn't really "Finding your "current method" in Java during runtime" it is more "Finding the calling method in Java during runtime"? – Nexevis Feb 10 '22 at 14:50
  • @Nexevis That sounds fairly correct. Maybe it's more like "I want a method that can identify which method it is called by" – Anju Maaka Feb 10 '22 at 14:51
  • @Anju Maaka I think your title is a bit confusing then, because that is pretty different than finding current method. – Nexevis Feb 10 '22 at 14:52
  • @Nexevis Fair point. I edited it to something I hope is clearer – Anju Maaka Feb 10 '22 at 14:54

1 Answers1

3

This can be done using a StackWalker (since Java 9). It does not directly provide a Method but enough information to create one. Here the basic idea, can be improved (e.g. better Exception(s)):

import java.lang.StackWalker.Option;
import java.lang.StackWalker.StackFrame;
import java.lang.reflect.Method;

public class MethodFinder {

    public static Method method() {
        return StackWalker.getInstance(Option.RETAIN_CLASS_REFERENCE).walk(stream -> 
            stream
            .filter(MethodFinder::notThisClass)
            .findFirst()
            .map(MethodFinder::frameToMethod))
            .orElseThrow();
    }
    
    private static boolean notThisClass(StackFrame frame) {
        return frame.getDeclaringClass() != MethodFinder.class;
    }
    
    private static Method frameToMethod(StackFrame frame) {
        var cl = frame.getDeclaringClass();
        try {
            return cl.getDeclaredMethod(frame.getMethodName(), frame.getMethodType().parameterArray());
        } catch (NoSuchMethodException | SecurityException ex) {
            throw new RuntimeException(ex);
        }
    }
}

To be used like Method myself = MethodFinder.method().

user16320675
  • 135
  • 1
  • 3
  • 9