Some advanced applications of java reflection

Source: Internet
Author: User

Java reflection can bypass access permissions and access non-public methods and members of the class. This may cause security discussions. The use of reflection helps solve many complicated problems, such as the type check during running, dynamic calling, and proxy implementation. Reflection brings us great flexibility to write programs, many functions are based on reflection.

Reflection also allows you to access private attributes of internal and anonymous internal classes.

 


The following provides a method to use the security manager and reflection token non-public methods and members.

 

 

Java runtime relies on a security manager to check whether the calling code has sufficient permissions for a specific access. Specifically, the security manager is a java. lang. SecurityManager class or a class that extends from this class, And it checks the operation permissions of some applications at runtime. In other words, all object access must be delegated to the security manager before executing its own logic. When access is controlled by the security manager, the application can only perform operations that are specifically permitted by the relevant security policy. Therefore, once started, the security manager can provide sufficient protection for the code. By default, the security manager is not set. Unless the Code explicitly installs a default or custom security manager, the access control check during runtime does not work. We can avoid Java access control check during runtime to achieve our access to non-public member variables or methods. To access the Non-Public members we need, we also need to use Java reflection technology. Java reflection is a powerful tool that allows us to configure Code while running without having to link source code between objects, making code more flexible. During compilation, the Java compiler ensures the private properties of private members, so that the private methods and private member variables of a class cannot be statically referenced by other classes. However, the Java reflection mechanism allows us to query and access variables and methods at runtime. Because reflection is dynamic, the check at compilation will no longer work.

The following code demonstrates how to use the security manager and reflection mechanism to access private variables.

// Obtain the value of the specified variable
Public static Object getValue (Object instance, String fieldName) throws IllegalAccessException, NoSuchFieldException {
Field field = getField (instance. getClass (), fieldName );
// If the parameter value is true, the access control check is disabled.
Field. setAccessible (true );
Return field. get (instance );
}
// This method obtains the value of this variable based on the variable name.
Public static Field getField (Class thisClass, String fieldName) throws NoSuchFieldException {
If (thisClass = null ){
Throw new NoSuchFieldException ("Error field! ");
}
}
 
 
 


GetField (instance. getClass (), fieldName) obtains object attributes through the reflection mechanism. You can reset the value of a variable by using the set method, such as field. set (instance, newValue );. If a security manager exists, the method first uses this and Member. DECLARED as parameters to call the checkMemberAccess method of the security manager. here this is the parent class of this class or the Member is determined. If the class is in the package, the method also uses the package name as the parameter to call the checkPackageAccess method of the security manager. Every call may cause SecurityException. When the access is denied, both call methods generate a securityexception.

The setAccessible (true) method disables the access control check by setting the parameter value to true, so that the variable can be called by other classes. We can extend a common basic class java. lang. reflect. AccessibleObject in the class we write. This class defines a setAccessible method that enables or disables access detection for one of these classes. The problem with this method is that if the security manager is used, it will detect whether the code that is disabling access detection allows this. If not, the security manager throws an exception.

In addition to accessing private variables, we can also use this method to access private methods.

Public static Method getMethod (Object instance, String methodName, Class [] classTypes) throws NoSuchMethodException {
Method accessMethod = getMethod (instance. getClass (), methodName, classTypes );
// If the parameter value is true, the access control check is disabled.
AccessMethod. setAccessible (true );
Return accessMethod;
}
Private static Method getMethod (Class thisClass, String methodName, Class [] classTypes) throws NoSuchMethodException {
If (thisClass = null ){
Throw new NoSuchMethodException ("Error method! ");
}
Try {
Return thisClass. getDeclaredMethod (methodName, classTypes );
} Catch (NoSuchMethodException e ){
Return getMethod (thisClass. getSuperclass (), methodName, classTypes );
}
}
 
 
 


The principle of obtaining a private method is the same as that of obtaining a private variable. When we get the function, we need to call it. In this case, we need to use the invoke () method to call the function. The code example is as follows:

Public static Object invokeMethod (Object instance, String methodName, Object arg) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
Object [] args = new Object [1];
Args [0] = arg;
Return invokeMethod (instance, methodName, args );
}
// Call a method containing multiple parameters
Public static Object invokeMethod (Object instance, String methodName, Object [] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
Class [] classTypes = null;
If (args! = Null ){
ClassTypes = new Class [args. length];
For (int I = 0; I <args. length; I ++ ){
If (args [I]! = Null ){
ClassTypes [I] = args [I]. getClass ();
}
}
}
Return getMethod (instance, methodName, classTypes). invoke (instance, args );
}
 
 
 


Using security manager and reflection, you can access private members without modifying the source code, which brings great convenience for testing. This method can be compiled smoothly, especially during compilation. However, this method also has some disadvantages. The first is the performance problem. Reflection is much slower than direct code for field and method access. The second is permission issues. Some Java-related program code does not have the permission to modify the security manager. In this case, this method is invalid.

 

FAQs:

 

Java reflection calls static methods


Class c;
C = Class. forName ("class name ");
Method m = c. getMethod ("method name", new Class [] {int. class, int. class });
M. invoke (c, new Object [] {1, 2, 3, 4 });
 
 
 

 

Retrieve generic information using reflection


1. Traditionally, using reflection to obtain function parameters and return values

Import java. lang. reflect. Method;
Public class Foo {
Public static void main (String [] args) throws Exception {
Method [] methods = Foo. class. getDeclaredMethods ();
For (Method method: methods ){
Class [] paramTypeList = method. getParameterTypes ();

Class returnType = method. getReturnType ();
System. out. println (returnType );
For (Class clazz: paramTypeList ){
System. out. println (clazz );
}
System. out. println ();
}
}

Public static String test1 (String str ){
Return null;
}

Public static Integer test2 (String str, Integer I ){
Return null;
}

}
 
 
 
 
2. Obtain the generic information of the Set classes for parameters and returned values when there is a wildcard type.

Import java. lang. reflect. Method;
Import java. lang. reflect. ParameterizedType;
Import java. lang. reflect. Type;
Import java. util. Map;
Import java. util. List;
Public class Foo {
Public static void main (String [] args) throws Exception {
Method [] methods = Foo. class. getDeclaredMethods ();
For (Method method: methods ){
System. out. println ("returnType :");
Type returnType = method. getGenericReturnType ();
If (returnType instanceof ParameterizedType ){
Type [] types = (ParameterizedType) returnType). getActualTypeArguments ();
For (Type type: types ){
System. out. println (type );
}
}
System. out. println ("paramTypeType :");
Type [] paramTypeList = method. getGenericParameterTypes ();
For (Type paramType: paramTypeList ){
If (paramType instanceof ParameterizedType ){
Type [] types = (ParameterizedType) paramType). getActualTypeArguments ();
For (Type type: types ){
System. out. println (type );
}
}
}
& Nb

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.