Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I know that we can access private constructor via reflection as @Sanjay T. Sharma mentioned in his answer of my question: Does “instanceof Void” always return false?

However, @duffymo said:

you can access private everything with reflection - methods, constructors, data members, everything.

  1. How can I access the private methods and the private data members?
  2. Is it possible to access local variable via reflection?
  3. Is there a way to prevent anyone from accessing private constructors, methods, and data members?
like image 721
Eng.Fouad Avatar asked Jul 14 '12 12:07

Eng.Fouad


People also ask

Is it possible to get information about private fields methods using reflection?

Yes it is possible. You need to use the getDeclaredField method (instead of the getField method), with the name of your private field: Field privateField = Test.

Can Java reflection API access private fields and methods of a class?

Despite the common belief it is actually possible to access private fields and methods of other classes via Java Reflection.


1 Answers

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 
like image 126
Pshemo Avatar answered Oct 07 '22 19:10

Pshemo