Sanyam Goel
Sanyam Goel

Reputation: 2180

Method signature through call stack introspection

Is there any way of finding the signature of a called method through call stack introspection. Do we have any alternatives for finding out the same. I do not have the source code and have only bytecode files

Thanks in advance.

Upvotes: 2

Views: 1109

Answers (3)

Mzzl
Mzzl

Reputation: 4136

The StackTraceElement does not contain any information about the parameters, so if you have multiple methods in the calling class with the same name and you want to know which one, you will need access to the source. In the case of the original question, you could try recreating the sources with a decompiler, compile from those sources, then recreate the stack trace and look at the line number in the recreated sources.

If overloaded methods are not a concern, this is what you can do:

public class TestTest {
    @Test
    public void overloaded1() throws Exception {
        doTheThing("foo", 42, this);
    }

    @Test
    public void overloaded2() throws Exception {
        doTheThing(1);
    }

    @Test
    public void notOverloaded() throws Exception {
        printMethodSignature();
    }

    public void doTheThing(int overloaded) throws Exception {
        printMethodSignature();
    }

    public void doTheThing(String dumm1, int dummy2, Object dummy3) throws Exception {
        printMethodSignature();
    }

    public void printMethodSignature() throws Exception {
        StackTraceElement[] elements = Thread.currentThread().getStackTrace();
        // elements[0] will contain java.lang.Thread.getStackTrace() here
        // elements[1] will contain this method: printMethodSignature()
        // elements[2] will contain the method from which printMethodSignature() was called

        System.out.println(elements[2] + " -> " + toSignature(elements[2]));
    }

    // Represent class & method as string
    public String toSignature(StackTraceElement st) throws Exception {
        Class callingClass = Class.forName(st.getClassName());
        return Stream.of(callingClass.getMethods())
            .filter(m -> m.getName().equals(st.getMethodName()))
            .map(m -> String.format("%s.%s(%s)", callingClass.getName(), m.getName(), toSignature(m)))
            .collect(Collectors.joining("\n"));
    }

    // Represent parameters as a String
    public String toSignature(Method method) {
        return Stream.of(method.getParameters())
            .map(p -> p.getParameterizedType().getTypeName())
            .collect(Collectors.joining(", "));
    }
}

Upvotes: 0

mprabhat
mprabhat

Reputation: 20323

Stack introspection will give you the caller of the method or at best few details of the method, for exact method signature you will have to use reflection.

StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();

Official documentation says:

Returns an array of stack trace elements representing the stack dump of this thread. This method will return a zero-length array if this thread has not started or has terminated. If the returned array is of non-zero length then the first element of the array represents the top of the stack, which is the most recent method invocation in the sequence. The last element of the array represents the bottom of the stack, which is the least recent method invocation in the sequence.

This way from StackTrace you can get the method name, filename, linenumber.

For complete method signature you will have to use reflection

Upvotes: 4

amicngh
amicngh

Reputation: 7899

You can use Java Reflection and StackTraceElement .

StackTraceElement[] elements = new Throwable().getStackTrace();

    String calleeMethod = elements[0].getMethodName();
    String callerMethodName = elements[1].getMethodName();
    String callerClassName = elements[1].getClassName();

    System.out.println("CallerClassName=" + callerClassName + " , Caller method name: " + callerMethodName);
    System.out.println("Callee method name: " + calleeMethod);

Upvotes: 0

Related Questions