Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>We can almost get there, here's a method that works in many cases. The problem is: it won't work reliably if there are overloaded methods (multiple methods with the same name). The stack trace does not provide the arguments, unfortunately.</p> <pre><code>private static Method getCallingMethod() throws ClassNotFoundException{ final Thread t = Thread.currentThread(); final StackTraceElement[] stackTrace = t.getStackTrace(); final StackTraceElement ste = stackTrace[2]; final String methodName = ste.getMethodName(); final String className = ste.getClassName(); Class&lt;?&gt; kls = Class.forName(className); do{ for(final Method candidate : kls.getDeclaredMethods()){ if(candidate.getName().equals(methodName)){ return candidate; } } kls = kls.getSuperclass(); } while(kls != null); return null; } </code></pre> <p><strong>Test code:</strong></p> <pre><code>public static void main(final String[] args) throws Exception{ System.out.println(getCallingMethod()); } </code></pre> <p><strong>Output:</strong></p> <blockquote> <p>public static void foo.bar.Phleem.main(java.lang.String[]) throws java.lang.Exception</p> </blockquote> <hr> <p>OK, here is a solution using <a href="http://asm.ow2.org/" rel="nofollow">ASM</a>. It works for almost all cases:</p> <pre><code>private static Method getCallingMethod() throws ClassNotFoundException, IOException{ final Thread t = Thread.currentThread(); final StackTraceElement[] stackTrace = t.getStackTrace(); final StackTraceElement ste = stackTrace[2]; final String methodName = ste.getMethodName(); final int lineNumber = ste.getLineNumber(); final String className = ste.getClassName(); final Class&lt;?&gt; kls = Class.forName(className); final ClassReader cr = new ClassReader(className); final EmptyVisitor empty = new EmptyVisitor(); final AtomicReference&lt;Method&gt; holder = new AtomicReference&lt;Method&gt;(); cr.accept(new ClassAdapter(empty){ @Override public MethodVisitor visitMethod( final int access, final String name, final String desc, final String signature, final String[] exceptions){ return name.equals(methodName) ? new MethodAdapter(empty){ @Override public void visitLineNumber(final int line, final Label start){ if(line &gt;= lineNumber &amp;&amp; holder.get() == null){ final Type[] argumentTypes = Type.getArgumentTypes(desc); final Class&lt;?&gt;[] argumentClasses = new Class[argumentTypes.length]; try{ for(int i = 0; i &lt; argumentTypes.length; i++){ final Type type = argumentTypes[i]; final String dd = type.getDescriptor(); argumentClasses[i] = getClassFromType(type); } holder.set(kls.getDeclaredMethod(methodName, argumentClasses)); } catch(final ClassNotFoundException e){ throw new IllegalStateException(e); } catch(final SecurityException e){ throw new IllegalStateException(e); } catch(final NoSuchMethodException e){ throw new IllegalStateException(e); } } super.visitLineNumber(line, start); } private Class&lt;?&gt; getClassFromType(final Type type) throws ClassNotFoundException{ Class&lt;?&gt; javaType; final String descriptor = type.getDescriptor(); if(type.equals(Type.INT_TYPE)){ javaType = Integer.TYPE; } else if(type.equals(Type.LONG_TYPE)){ javaType = Long.TYPE; } else if(type.equals(Type.DOUBLE_TYPE)){ javaType = Double.TYPE; } else if(type.equals(Type.FLOAT_TYPE)){ javaType = Float.TYPE; } else if(type.equals(Type.BOOLEAN_TYPE)){ javaType = Boolean.TYPE; } else if(type.equals(Type.BYTE_TYPE)){ javaType = Byte.TYPE; } else if(type.equals(Type.CHAR_TYPE)){ javaType = Character.TYPE; } else if(type.equals(Type.SHORT_TYPE)){ javaType = Short.TYPE; } else if(descriptor.startsWith("[")){ final Class&lt;?&gt; elementType = getClassFromType(type.getElementType()); javaType = Array.newInstance(elementType, 0).getClass(); } else{ javaType = Class.forName(type.getClassName()); } return javaType; } } : null; } }, 0); return holder.get(); } </code></pre> <p>I'll leave it to you to refactor this into something readable. And it won't work if the signature of the calling method contains primitive arrays or multidimensional arrays. Obviously it only works if the class file contains line numbers.</p> <p>Argghh, I work for ages and then I see that someone has come up with an almost identical solution!!! Anyway, I'll leave mine, because I developed it independently.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload