Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get callers method (java.lang.reflect.Method)

I would like to get the calling method java.lang.reflect.Method. NOT the name of the method.

Here is an example how to get the callers Class.

// find the callers class
Thread t = Thread.getCurrentThread();
Class<?> klass = Class.forName(t.getStackTrace()[2].getClassName());
// do something with the class (like processing its annotations)
... 

It's for testing purpose only!

like image 283
dacwe Avatar asked Oct 26 '10 14:10

dacwe


People also ask

How do I use the Java Lang reflect method?

This method returns annotations that are directly present on this element. This method returns the Class object representing the class or interface that declares the executable represented by this object. This method returns the default value for the annotation member represented by this Method instance.

What is Java Lang reflect?

lang. reflect Description. Provides classes and interfaces for obtaining reflective information about classes and objects.

What is caller method in Java?

The calling method is the method that contains the actual call. The called method is the method being called. They are different. They are also called the Caller and the Callee methods. For example int caller(){ int x=callee(); } int callee(){ return 5; }


1 Answers

If it's just for testing, then this may work. It assumes that the class files are accessible via the calling class's ClassLoader and that the class files were compiled with debugging symbols (which I hope they are for testing!). This code relies on the ASM bytecode library.

public static Method getMethod(final StackTraceElement stackTraceElement) throws Exception {
    final String stackTraceClassName = stackTraceElement.getClassName();
    final String stackTraceMethodName = stackTraceElement.getMethodName();
    final int stackTraceLineNumber = stackTraceElement.getLineNumber();
    Class<?> stackTraceClass = Class.forName(stackTraceClassName);

    // I am only using AtomicReference as a container to dump a String into, feel free to ignore it for now
    final AtomicReference<String> methodDescriptorReference = new AtomicReference<String>();

    String classFileResourceName = "/" + stackTraceClassName.replaceAll("\\.", "/") + ".class";
    InputStream classFileStream = stackTraceClass.getResourceAsStream(classFileResourceName);

    if (classFileStream == null) {
        throw new RuntimeException("Could not acquire the class file containing for the calling class");
    }

    try {
        ClassReader classReader = new ClassReader(classFileStream);
        classReader.accept(
                new EmptyVisitor() {
                    @Override
                    public MethodVisitor visitMethod(int access, final String name, final String desc, String signature, String[] exceptions) {
                        if (!name.equals(stackTraceMethodName)) {
                            return null;
                        }

                        return new EmptyVisitor() {
                            @Override
                            public void visitLineNumber(int line, Label start) {
                                if (line == stackTraceLineNumber) {
                                    methodDescriptorReference.set(desc);
                                }
                            }
                        };
                    }
                },
                0
            );
    } finally {
        classFileStream.close();
    }

    String methodDescriptor = methodDescriptorReference.get();

    if (methodDescriptor == null) {
        throw new RuntimeException("Could not find line " + stackTraceLineNumber);
    }

    for (Method method : stackTraceClass.getMethods()) {
        if (stackTraceMethodName.equals(method.getName()) && methodDescriptor.equals(Type.getMethodDescriptor(method))) {
            return method;
        }
    }

    throw new RuntimeException("Could not find the calling method");
}
like image 144
Adam Paynter Avatar answered Oct 21 '22 14:10

Adam Paynter