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 returnpublic
methods, to get private ones usegetDeclaredMethod
on type which declares it. - you are invoking your method on
"method"
String literal instead of instance ofA
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
Why Are Interface Variables Static and Final by Default
How to Change Jdk Version for an Eclipse Project
@Requestbody and @Responsebody Annotations in Spring
Rotating Coordinate Plane for Data and Text in Java
Convert Java.Util.Date to What "Java.Time" Type
Using Sleep() for a Single Thread
Collections.Sort with Multiple Fields
Best Practice for Setting Jframe Locations
How to Validate Two or More Fields in Combination
Most Efficient Conversion of Resultset to JSON
How to Determine the Class of a Generic Type
How to Specify the Schema When Connecting to Postgres with Jdbc
Individual and Not Continuous Jtable's Cell Selection
Java.Lang.Unsatisfiedlinkerror No *****.Dll in Java.Library.Path
How to Change UI Depending on Combo Box Selection