[java] Any way to Invoke a private method?

I have a class that uses XML and reflection to return Objects to another class.

Normally these objects are sub fields of an external object, but occasionally it's something I want to generate on the fly. I've tried something like this but to no avail. I believe that's because Java won't allow you to access private methods for reflection.

Element node = outerNode.item(0);
String methodName = node.getAttribute("method");
String objectName = node.getAttribute("object");

if ("SomeObject".equals(objectName))
    object = someObject;
else
    object = this;

method = object.getClass().getMethod(methodName, (Class[]) null);

If the method provided is private, it fails with a NoSuchMethodException. I could solve it by making the method public, or making another class to derive it from.

Long story short, I was just wondering if there was a way to access a private method via reflection.

This question is related to java reflection private

The answer is


you can do this using ReflectionTestUtils of Spring (org.springframework.test.util.ReflectionTestUtils)

ReflectionTestUtils.invokeMethod(instantiatedObject,"methodName",argument);

Example : if you have a class with a private method square(int x)

Calculator calculator = new Calculator();
ReflectionTestUtils.invokeMethod(calculator,"square",10);

If the method accepts non-primitive data type then the following method can be used to invoke a private method of any class:

public static Object genericInvokeMethod(Object obj, String methodName,
            Object... params) {
        int paramCount = params.length;
        Method method;
        Object requiredObj = null;
        Class<?>[] classArray = new Class<?>[paramCount];
        for (int i = 0; i < paramCount; i++) {
            classArray[i] = params[i].getClass();
        }
        try {
            method = obj.getClass().getDeclaredMethod(methodName, classArray);
            method.setAccessible(true);
            requiredObj = method.invoke(obj, params);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }

        return requiredObj;
    }

The Parameter accepted are obj, methodName and the parameters. For example

public class Test {
private String concatString(String a, String b) {
    return (a+b);
}
}

Method concatString can be invoked as

Test t = new Test();
    String str = (String) genericInvokeMethod(t, "concatString", "Hello", "Mr.x");

You can use Manifold's @Jailbreak for direct, type-safe Java reflection:

@Jailbreak Foo foo = new Foo();
foo.callMe();

public class Foo {
    private void callMe();
}

@Jailbreak unlocks the foo local variable in the compiler for direct access to all the members in Foo's hierarchy.

Similarly you can use the jailbreak() extension method for one-off use:

foo.jailbreak().callMe();

Through the jailbreak() method you can access any member in Foo's hierarchy.

In both cases the compiler resolves the method call for you type-safely, as if a public method, while Manifold generates efficient reflection code for you under the hood.

Alternatively, if the type is not known statically, you can use Structural Typing to define an interface a type can satisfy without having to declare its implementation. This strategy maintains type-safety and avoids performance and identity issues associated with reflection and proxy code.

Discover more about Manifold.


One more variant is using very powerfull JOOR library https://github.com/jOOQ/jOOR

MyObject myObject = new MyObject()
on(myObject).get("privateField");  

It allows to modify any fields like final static constants and call yne protected methods without specifying concrete class in the inheritance hierarhy

<!-- https://mvnrepository.com/artifact/org.jooq/joor-java-8 -->
<dependency>
     <groupId>org.jooq</groupId>
     <artifactId>joor-java-8</artifactId>
     <version>0.9.7</version>
</dependency>

Let me provide complete code for execution protected methods via reflection. It supports any types of params including generics, autoboxed params and null values

@SuppressWarnings("unchecked")
public static <T> T executeSuperMethod(Object instance, String methodName, Object... params) throws Exception {
    return executeMethod(instance.getClass().getSuperclass(), instance, methodName, params);
}

public static <T> T executeMethod(Object instance, String methodName, Object... params) throws Exception {
    return executeMethod(instance.getClass(), instance, methodName, params);
}

@SuppressWarnings("unchecked")
public static <T> T executeMethod(Class clazz, Object instance, String methodName, Object... params) throws Exception {

    Method[] allMethods = clazz.getDeclaredMethods();

    if (allMethods != null && allMethods.length > 0) {

        Class[] paramClasses = Arrays.stream(params).map(p -> p != null ? p.getClass() : null).toArray(Class[]::new);

        for (Method method : allMethods) {
            String currentMethodName = method.getName();
            if (!currentMethodName.equals(methodName)) {
                continue;
            }
            Type[] pTypes = method.getParameterTypes();
            if (pTypes.length == paramClasses.length) {
                boolean goodMethod = true;
                int i = 0;
                for (Type pType : pTypes) {
                    if (!ClassUtils.isAssignable(paramClasses[i++], (Class<?>) pType)) {
                        goodMethod = false;
                        break;
                    }
                }
                if (goodMethod) {
                    method.setAccessible(true);
                    return (T) method.invoke(instance, params);
                }
            }
        }

        throw new MethodNotFoundException("There are no methods found with name " + methodName + " and params " +
            Arrays.toString(paramClasses));
    }

    throw new MethodNotFoundException("There are no methods found with name " + methodName);
}

Method uses apache ClassUtils for checking compatibility of autoboxed params


Use getDeclaredMethod() to get a private Method object and then use method.setAccessible() to allow to actually call it.


Examples related to java

Under what circumstances can I call findViewById with an Options Menu / Action Bar item? How much should a function trust another function How to implement a simple scenario the OO way Two constructors How do I get some variable from another class in Java? this in equals method How to split a string in two and store it in a field How to do perspective fixing? String index out of range: 4 My eclipse won't open, i download the bundle pack it keeps saying error log

Examples related to reflection

Get properties of a class Get class name of object as string in Swift Set field value with reflection Using isKindOfClass with Swift I want to get the type of a variable at runtime Loading DLLs at runtime in C# How to have Java method return generic list of any type? Java reflection: how to get field value from an object, not knowing its class Dynamically Add C# Properties at Runtime Check if a property exists in a class

Examples related to private

Private class declaration Python read-only property What is the use of a private static variable in Java? How to access private data members outside the class without making "friend"s? JUnit Testing private variables? What are access specifiers? Should I inherit with private, protected or public? Do subclasses inherit private fields? What is the difference between public, private, and protected? Internal vs. Private Access Modifiers Private Variables and Methods in Python