Any Way to Invoke a Private Method

Any way to Invoke a private method?

You can invoke private method with reflection. Modifying the last bit of the posted code:

Method method = object.getClass().getDeclaredMethod(methodName);
method.setAccessible(true);
Object r = method.invoke(object);

There are a couple of caveats. First, getDeclaredMethod will only find method declared in the current Class, not inherited from supertypes. So, traverse up the concrete class hierarchy if necessary. Second, a SecurityManager can prevent use of the setAccessible method. So, it may need to run as a PrivilegedAction (using AccessController or Subject).

How to call private method by other methods?

Within the class you should be able to call method1();

Outside the class you will need to call it from an instance of that class and will have access to public methods only

How do I access private methods and private data members via reflection?

1) How can I access the private methods and the private data members?

You can do it with a little help of the setAccessible(true) method:

class Dummy{
private void foo(){
System.out.println("hello foo()");
}
private int i = 10;
}

class Test{
public static void main(String[] args) throws Exception {
Dummy d = new Dummy();

/*--- [INVOKING PRIVATE METHOD] ---*/
Method m = Dummy.class.getDeclaredMethod("foo");
//m.invoke(d); // Exception java.lang.IllegalAccessException
m.setAccessible(true);//Abracadabra
m.invoke(d); // Now it's OK

/*--- [GETING VALUE FROM PRIVATE FIELD] ---*/
Field f = Dummy.class.getDeclaredField("i");
//System.out.println(f.get(d)); // Not accessible now
f.setAccessible(true); // Abracadabra
System.out.println(f.get(d)); // Now it's OK

/*--- [SETTING VALUE OF PRIVATE FIELD] ---*/
Field f2 = Dummy.class.getDeclaredField("i");
//f2.set(d,20); // Not accessible now
f2.setAccessible(true); // Abracadabra
f2.set(d, 20); // Now it's OK
System.out.println(f2.get(d));
}
}

2) Is it possible to access a local variable via reflection?

No. Local variables cannot be accessed outside of a block in which they were created (someone could say that you can assign such a variable to a field like field = localVariable; and later access such a field via reflection, but this way we will be accessing the value, not the variable).

3) Is there any way to prevent anyone from accessing private constructors, methods, and data members?

I think for constructors or methods you could use stacktrace to check if it was invoked by Reflection.

For fields I can't find a solution to prevent accessing them via reflection.

[WARNING: This is not approved by anyone. I just wrote it inspired by your question.]

class Dummy {
private void safeMethod() {
StackTraceElement[] st = new Exception().getStackTrace();
// If a method was invoked by reflection, the stack trace would be similar
// to something like this:
/*
java.lang.Exception
at package1.b.Dummy.safeMethod(SomeClass.java:38)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
-> at java.lang.reflect.Method.invoke(Method.java:601)
at package1.b.Test.main(SomeClass.java:65)
*/
//5th line marked by "->" is interesting one so I will try to use that info

if (st.length > 5 &&
st[4].getClassName().equals("java.lang.reflect.Method"))
throw new RuntimeException("safeMethod() is accessible only by Dummy object");

// Now normal code of method
System.out.println("code of safe method");
}

// I will check if it is possible to normally use that method inside this class
public void trySafeMethod(){
safeMethod();
}

Dummy() {
safeMethod();
}
}

class Dummy1 extends Dummy {}

class Test {
public static void main(String[] args) throws Exception {
Dummy1 d1 = new Dummy1(); // safeMethod can be invoked inside a superclass constructor
d1.trySafeMethod(); // safeMethod can be invoked inside other Dummy class methods
System.out.println("-------------------");

// Let's check if it is possible to invoke it via reflection
Method m2 = Dummy.class.getDeclaredMethod("safeMethod");
// m.invoke(d);//exception java.lang.IllegalAccessException
m2.setAccessible(true);
m2.invoke(d1);
}
}

Output from Test main method:

code of safe method
code of safe method
-------------------
Exception in thread "main" java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at package1.b.Test.main(MyClass2.java:87)
Caused by: java.lang.RuntimeException: method safeMethod() is accessible only by Dummy object
at package1.b.Dummy.safeMethod(MyClass2.java:54)
... 5 more

How to invoke private method via Reflection when parameter of method is List?

There are two problems in your code

  • you are using getMethod which can only return public methods, to get private ones use getDeclaredMethod on type which declares it.
  • you are invoking your method on "method" String literal instead of instance of A class (String doesn't have this method, so you can't invoke it on its instance. For now your code is equivalent to something like "method".method(yourList) which is not correct).

Your code should look like

Class<A> clazz = A.class;
Method met = clazz.getDeclaredMethod("method", List.class);
// ^^^^^^^^
met.setAccessible(true);
String res = (String) met.invoke(new A(), new ArrayList<Integer>());
// ^^^^^^^

//OR pass already existing instance of A class
//A myA = new A(); //other instance of A on which you want to call the method
//...
//String res = (String) met.invoke(myA, new ArrayList<Integer>());

System.out.println(res);

How do I use reflection to access a private method?

getDeclaredMethod needs you to pass the parameter types so that it can resolve overloaded methods.

Since your foo method has a single parameter of type String, the following should work:

Method m = Dummy.class.getDeclaredMethod("foo", String.class);

And of course you also need to change the invoke call to pass a string.

How to call a private method from outside a java class

use setAccessible(true) on your Method object before using its invoke method.

import java.lang.reflect.*;
class Dummy{
private void foo(){
System.out.println("hello foo()");
}
}

class Test{
public static void main(String[] args) throws Exception {
Dummy d = new Dummy();
Method m = Dummy.class.getDeclaredMethod("foo");
//m.invoke(d);// throws java.lang.IllegalAccessException
m.setAccessible(true);// Abracadabra
m.invoke(d);// now its OK
}
}

Access to private methods in private class

No, you can't.

The private modifier specifies that the member can only be accessed in its own class

So, if you want to access to private methods, then you should define them with the public, protected or no modifier depending what is more appropriate in that case.

See more in this doc

How can a derived class invoke private method of base class?

Because you defined the main method in PrivateOverride class. If you put the main method in Derived class, it would not compile, because .f() would not be visible there.

po.f() call in PrivateOverride class is not a polymorphism, because the f() in PrivateOverride class is private, so f() in Derived class is not overriden.

How to call a private method of a class in different package

If you want to do that you should make it public or make a public wrapper method it.

If thats not possible, you can work your way around it, but thats ugly and bad and you should have really good reasons to do so.

public boolean importBook(String epubBookPath){
//The function that adds books to database.
}

or

public boolean importBookPublic(String epubBookPath){
return importBook(epubBookPath);
}
private boolean importBook(String epubBookPath){
//The function that adds books to database.
}

Also note that if you CAN'T access the method directly in a third-party library than it is most likely INTENDED that way. Take a look at the call hierarchy of the private method and see if you find a public method that does the call to the private one and that also does what you need.

Libraries are often designed in a way that a public method does some checking (all Parameters given, authenticated etc.) and then pass the call to the private method to do the actual work. You almost never want to work around that process.



Related Topics



Leave a reply



Submit