Reputation: 2180
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
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
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
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