sun.reflect.Reflection.getCallerClass Example

0

In this article, we will determine the caller class using sun.reflect.Reflection.getCallerClass() method. This class comes with Sun’s JVM and is part of sun.reflect package. The method we are going to look into is getCallerClass(index) where the index is the number of real frames up the stack. It ignores the frames associated with java.lang.reflect.Method.invoke() and its implementation. This method tells you which classes are in our call stack.
One key point to note about is the functionality of this class cannot be relied upon for all future versions of Java. If the class is not available then one can also make use of Throwable#getStackTrace() to navigate through the stack frame elements and find the stack frame one is interested in.

Consider some context class which holds the class of the caller. One can either provider a constructor which takes in the caller class or provide an empty constructor and derive the caller class.
Here we derive using sun.reflect.Reflection.getCallerClass(), the frames to skip is 2. One would be the frame containing ClassContext constructor and the other would be the SunReflectionUtil.getCallerClass() method.

ClassContext:

package com.javarticles.reflection;

public class ClassContext {
    private Class<?> clazz;
    
    public ClassContext() {  
        clazz = SunReflectionUtil.getCallerClass(2);
    }
    
    public ClassContext(Class<?> clazz) {
        this.clazz = clazz;
    }

    public Class<?> getCallerClass() {
        return clazz;
    }        
}

We still have to skip one more frame as we don’t want to include frame containing sun.reflect.Reflection.
In the static block, we load sun.reflect.Reflection if it exists.

SunReflectionUtil:

package com.javarticles.reflection;

import java.lang.reflect.Method;

public class SunReflectionUtil {
    private static final boolean SUN_REFLECTION_SUPPORTED;
    private static final Method GET_CALLER_CLASS;
    static {
        Method getCallerClass;
        try {
            final Class<?> sunReflectionClass = Class
                    .forName("sun.reflect.Reflection");
            getCallerClass = sunReflectionClass.getDeclaredMethod(
                    "getCallerClass", int.class);            
        } catch (final Exception e) {
            System.out.println(
                    "sun.reflect.Reflection.getCallerClass is not supported." + e);
            getCallerClass = null;
        }
        SUN_REFLECTION_SUPPORTED = getCallerClass != null;
        GET_CALLER_CLASS = getCallerClass;
    }

    public static Class<?> getCallerClass(final int index) {
        try {
            int i = 0;
            Class<?> clazz = (Class<?>) GET_CALLER_CLASS.invoke(null, i);
            while (clazz != null) {
                System.out.println("Caller class at index[" + i + "]->" + clazz.getName());
                clazz = (Class<?>) GET_CALLER_CLASS.invoke(null, ++i);
            }
        } catch (Exception e) {         
            System.out.println("Exception navigating through frames");
        }
        
        if (index < 0) {
            throw new IndexOutOfBoundsException(Integer.toString(index));
        }
        if (supportsFastReflection()) {
            try {
                return (Class<?>) GET_CALLER_CLASS.invoke(null, index + 1);
            } catch (final Exception e) {
                System.out.println("Error in ReflectionUtil.getCallerClass({}), index<" + index + ">" + ", exception< " + e + ">");
                return null;
            }
        }        
        return null;
    }
    
    public static boolean supportsFastReflection() {
        return SUN_REFLECTION_SUPPORTED;
    }

}

We create an instance of ClassContext and then verify that the caller class exists.

SunReflectionExample:

package com.javarticles.reflection;


public class SunReflectionExample {
    public static void main(String[] args) throws Exception {
        ClassContext classContext = new ClassContext();
        System.out.println(classContext.getCallerClass().getName());
    }
}

You can see here the caller class at each frame and then the one we are looking out for at index 3.
Output:

Caller class at index[0]->sun.reflect.Reflection
Caller class at index[1]->com.javarticles.reflection.SunReflectionUtil
Caller class at index[2]->com.javarticles.reflection.ClassContext
Caller class at index[3]->com.javarticles.reflection.SunReflectionExample
com.javarticles.reflection.SunReflectionExample

Download the source code

This was an example about determining caller class using sun.reflect.Reflection.

You can download the source code here: javaSunReflectionCallerClassExample.zip
Share.

Comments are closed.