You can use bytecode utilities to get information about using bytecode. And then use the line number information in the StackTraceElement to get the method .
Here i am using javassist.
private static Optional<Method> get(StackTraceElement e) throws NotFoundException, ClassNotFoundException { Class<?> clz = Class.forName(e.getClassName()); int line = e.getLineNumber(); ClassPool pool = ClassPool.getDefault(); CtClass cc = pool.get(clz.getName()); return Observable.fromArray(cc.getDeclaredMethods()) .sorted(Comparator.comparing(m -> m.getMethodInfo().getLineNumber(0))) .filter(m -> m.getMethodInfo().getLineNumber(0) <= line) .map(Optional::of) .blockingLast(Optional.empty()) .map(m -> uncheck(() -> clz.getDeclaredMethod(m.getName(), Arrays.stream(m.getParameterTypes()).map(c -> uncheck(() -> nameToClass(c.getName()))).toArray(Class[]::new)))); } private static Class<?> nameToClass(String name) throws ClassNotFoundException { switch (name) { case "int": return int.class; case "short": return short.class; case "long": return long.class; case "double": return double.class; case "float": return float.class; case "boolean": return boolean.class; case "char": return char.class; case "byte": return byte.class; case "void": return void.class; } if (name.endsWith("[]")) { return Array.newInstance(nameToClass(name.substring(0, name.length() - 2)), 0).getClass(); } return Class.forName(name); }
uncheck my utility ignores an exception only in lambda, you can just use try-catch. see source here
then we check our code
public static void main(String[] args) throws Exception { // test normal System.out.println(get(new Exception().getStackTrace()[0])); // test lambda Runnable r = () -> System.out.println(uncheck(() -> get(new Exception().getStackTrace()[0]))); r.run(); // test function testHere(1); } private static void testHere(int i) throws Exception { System.out.println(get(new Exception().getStackTrace()[0])); }
and conclusion
Optional[public static void xdean.stackoverflow.java.reflection.Q44563354.main(java.lang.String[]) throws java.lang.Exception] Optional[private static java.util.Optional xdean.stackoverflow.java.reflection.Q44563354.lambda$1() throws java.lang.Exception] Optional[private static void xdean.stackoverflow.java.reflection.Q44563354.testHere(int) throws java.lang.Exception]
But note that this approach only works for a class that has bytecode in the classpath. If you use a dynamic proxy server, it does not work.
Find a complete code example here
EDIT . You can filter synthetic and bridge methods to get the actual method.
source share