How do I invoke a private static method using reflection (Java)?

JavaReflectionInvoke

Java Problem Overview


I would like to invoke a private static method. I have its name. I've heard it can be done using Java reflection mechanism. How can I do it?

EDIT: One problem I encountered when trying to invoke the method is how to specify the type of its argument. My method receives one argument and its type is Map. Therefore I cannot do Map<User, String>.TYPE (In run time there's no such a thing as Map because of Java Type erasure). Is there another way to get the method?

Java Solutions


Solution 1 - Java

Let's say you want to call MyClass.myMethod(int x);

Method m = MyClass.class.getDeclaredMethod("myMethod", Integer.TYPE);
m.setAccessible(true); //if security settings allow this
Object o = m.invoke(null, 23); //use null if the method is static

Solution 2 - Java

Invoke main from reflection tutorial

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;

public class InvokeMain {
    public static void main(String... args) {
	try {
	    Class<?> c = Class.forName(args[0]);
	    Class[] argTypes = new Class[] { String[].class };
	    Method main = c.getDeclaredMethod("main", argTypes);
  	    String[] mainArgs = Arrays.copyOfRange(args, 1, args.length);
	    System.out.format("invoking %s.main()%n", c.getName());
	    main.invoke(null, (Object)mainArgs);

        // production code should handle these exceptions more gracefully
	} catch (ClassNotFoundException x) {
	    x.printStackTrace();
	} catch (NoSuchMethodException x) {
	    x.printStackTrace();
	} catch (IllegalAccessException x) {
	    x.printStackTrace();
	} catch (InvocationTargetException x) {
	    x.printStackTrace();
	}
    }
}

Solution 3 - Java

No, you can't say Map<K,V>.class. This is because of type erasure. At runtime, there's no such thing.

Luckily, you can say just plain old Map.class. It's all the same at runtime.

If the warnings bother you, search for other questions related to generics and type erasure, there's a wealth of information on the subject here.

Solution 4 - Java

I use a single method that encapsulates getting the target method and then invoking it. Probably has some limitations, of course. Here is the method put into a class and its JUnit test:

public class Invoker {
/**
 * Get method and invoke it.
 * 
 * @author jbetancourt
 * 
 * @param name of method
 * @param obj Object to invoke the method on
 * @param types parameter types of method
 * @param args to method invocation
 * @return return value
 * @throws Exception for unforseen stuff
 */
public static final <T> Object invokeMethod(final String name, final T obj,
  final Class<?>[] types, final Object... args) throws Exception {

	Method method = obj.getClass().getDeclaredMethod(name, types);
	method.setAccessible(true);
	return method.invoke(obj, args);
}

/**
 * Embedded JUnit tests.
 */
@RunWith(JUnit4.class)
public static class InvokerTest {
	/** */
	@Test
	public void testInvoke() throws Exception {
		class TestTarget {
			private String hello() {
				return "Hello world!";
			}
		}

		String actual = (String) Invoker.invokeMethod("hello",
				new TestTarget(), new Class<?>[] {});
		String expected = "Hello world!";
		assertThat(actual, is(expected));

	}
}

}

Solution 5 - Java

Object insecure; //This needs to be an initialized reference

Class c = insecure.getClass();
Method m = c.getMethod(name, parameterTypes); //Fill the name and types in
m.setAccessible(true);
m.invoke( insecure, parameters ); //Fill in the parameters you would like

There are a number of checked exceptions which may be thrown. Both parameterTypes and parameters are ellipse arguments (variable length), fill them in as needed. The JVM by specification has a strongly typed calling convention so you need to know the parameter types.

With that said, unless you are writing some sort of application container, server component container, RMI-like system, or JVM based langauge you should avoid doing this.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionsnakileView Question on Stackoverflow
Solution 1 - JavaLandeiView Answer on Stackoverflow
Solution 2 - JavaCratylusView Answer on Stackoverflow
Solution 3 - JavabmarguliesView Answer on Stackoverflow
Solution 4 - JavaJosef.BView Answer on Stackoverflow
Solution 5 - JavaMarkView Answer on Stackoverflow