Reflection is one of the very powerful mechanism in Java which gives your program the ability to inspect characteristic and modify the internal state of a object at runtime.
Steps
1. Compiler insert a public static final field called class, which is an instance of java.lang.Class into the bytecode of compiled class.2. java.lang.Class has various methods that can be used to inspect and modify the object characteristic.
3. Assume we have a class as shown below
package sample;
import java.util.ArrayList;
import java.util.List;
public class SampleDemo {
public String name = "Manas"; // Public Methods
private int salary = 0; // Private Methods
public List<String> location = new ArrayList<String>();
// private constructor
private SampleDemo() {
}
// public constructor
public SampleDemo(String name) {
}
// public method
public void getName() {
System.out.println("My Name is XXX");
}
// private methods
private void getSalary() {
System.out.println("Salary is confidential");
}
// protected methos
protected void getGirlFriend() {
System.out.println("Cannot be disclosed to all the list is....");
}
// public setter method
public void setName(String name) {
this.name = name;
}
}
4. We create a class to inspect the demo class
package sample;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class ReflectionInspection {
public static void main(String[] args) throws NoSuchFieldException, SecurityException {
String className = SampleDemo.class.getSimpleName();
System.out.println("Class Name: " + className);
// inspect all public field
Field[] fields = SampleDemo.class.getFields();
for (int i = 0; i < fields.length; i++) {
System.out.println("Field name:" + fields[i]);
}
// To inspect the private variable we have to specify them explicitly
Field f = SampleDemo.class.getDeclaredField("salary");
System.out.println("private field " + f);
// inspect all public methods including getter and setter
Method[] methods = SampleDemo.class.getMethods();
for (int i = 0; i < methods.length; i++) {
methods[i].setAccessible(true);
System.out.println("Method name:" + methods[i]);
}
// inspect all constructors
Constructor[] constructors = SampleDemo.class.getConstructors();
for (int i = 0; i < constructors.length; i++) {
System.out.println("Constructor Name:" + constructors[i]);
}
}
}
5 Output
6. Conclusion
1. As we can see that all public methods, public constructors, and public fields can be easily listed.
2. For private fields and methods we have to specify the name explicitly to inspected
3. As all the class also extends the Object class we can see all the methods from Object class when we list all the methods.
7. Modify using reflection
package sample;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class ReflectionModify {
public static void main(String[] args) throws NoSuchMethodException, SecurityException, InstantiationException,
IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchFieldException {
String className = SampleDemo.class.getSimpleName();
System.out.println("Class Name: " + className);
Constructor c = SampleDemo.class.getDeclaredConstructor();
c.setAccessible(true);
SampleDemo sampleDemo = (SampleDemo) c.newInstance();
sampleDemo.getName();
Field f = SampleDemo.class.getDeclaredField("salary");
f.setAccessible(true);34e334xzgetInt(sampleDemo));
f.setInt(sampleDemo, 10);
System.out.println("private field " + f.getInt(sampleDemo));
Method m = SampleDemo.class.getDeclaredMethod("getSalary");
m.setAccessible(true);
m.invoke(sampleDemo);
}
}
8. Output
9 Conclusion
We can use the setAccessible(true) to modify access to the private field, method and constructor.
Once we have access to the private attribute we can even modify the value of that attribute
Additional information
1. Other ways to get a handle to the class we will be inspecting or modifying are as follows1.1. If we know the complete path of class file we can use below statement
Class c=Class.forName("pkgName.SampleDemo");
1.2 We create an instance of the class and use getClass() as shown below
Class c=obj.getClass();
2. Once we have Class instance it has number of methods to inspect or modify.
3. Reflection is part of java.reflect package.
Preventing Reflection
Basically it boils down to two question.
1. Whether you can prevent other peoples code to modify your class’s private attribute.
The answer is No. Once you distribute your code in form of jar, you do not have control over it as your code will be executed in another person JVM.
But if your code is accessed through some protocol such as HTTP and you have control over the server where code is getting executed you can definitively deploy security manager to prevent unwanted modification or access.
2. Whether you want to run your code in your environment in a manner that private attribute are not modified
The answer is Yes. Java by itself allows setAccessible to be used for only classes in JAVA_HOME and it does not allow modification from the class through untrustworthy applet.
You can also install security manager and use a more restrictive security policy which disallow classes referencing certain package.
One important point is permission for setAccessible is binary so you cannot selectively set some attribute as accessible and other as not-accessible in a class.
Areas where Reflection is used
1. Integrated Development Environment such as Eclipse.
Ever wondered when typing a dot(.) after object, IDE gives you list of all the method for that object or list of method that that needs to be implemented when you implement an interface.That is the power of reflection which inspect the class at runtime.
2. Framework such as struts and spring etc.
Framework use something like this in configuration file
<bean id="someId" class="com.sample.SampleDemo’/">
<property name="someField" value="someValue" />
</bean>
It is through reflection that the framework will invoke class.forName(“pkgName.className”) when it encounter bean tag in the xml and also set the property.
3. Testing tools
Testing tools such as Junit uses reflection to get set of @Test annotated method to invoke.
Additional resource can be found in below link
1. http://stackoverflow.com/questions/2481862/how-to-limit-setaccessible-to-only-legitimate-uses
1. http://stackoverflow.com/questions/2481862/how-to-limit-setaccessible-to-only-legitimate-uses
2.http://www.javatpoint.com/java-reflection
3. http://tutorials.jenkov.com/java-reflection/index.html
4. http://www.programmerinterview.com/index.php/java-questions/java-reflection-example/
3. http://tutorials.jenkov.com/java-reflection/index.html
4. http://www.programmerinterview.com/index.php/java-questions/java-reflection-example/






No comments:
Post a Comment