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.
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.
Despite the common belief it is actually possible to access private fields and methods of other classes via Java 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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With