深入理解反射机制(Java)

关于反射:

动态加载一个指定的类,获取该类中的所有内容。并将字节码文件中的内容都封装成对象,便于操作这些成员。

反射机制允许程序在执行期借助于Reflection API取得任何类的内部信息,并能直接操作任意对象的内部属性及方法

 

反射的好处:大大的增强了程序的扩展性。

 

Java反射机制提供的功能:

    • 判断任意一个对象所属的类、构造任意一个类的对象、判断任意一个类所具有的成员变量和方法、调用任意一个对象的成员变量和方法
    • Class对象,获取类的Fields、获取类的Method、获取类的Constructor

 

 

1.理解Class类并实例化Class类对象

2.运行时创建类对象并获取类的完整结构

3.通过反射调用类的指定方法、指定属性

4.动态代理

 

 

主要提供用途:

1.   在运行时判断任意一个对象所属的类

2.   在运行时构造任意一个类的对象

3.   在运行时判断任意一个类所具有的成员变量和方法

4.   在运行时调用任意一个对象的方法

 

 

反射的应用:

动态代理

 

反射的缺点:

Reflection is powerful, but should not be used indiscriminately. If it is possible to perform an operation without using reflection, then it is preferable to avoid using it. The following concerns should be kept in mind when accessing code via reflection.

尽管反射非常强大,但也不能滥用。如果一个功能可以不用反射完成,那么最好就不用。

在用反射技术时,下面几条内容应该牢记于心:

1.性能

反射包括了一些动态类型,所以 JVM 无法对这些代码进行优化。因此,反射操作的效率要比那些非反射操作低得多。应该避免在经常被执行的代码或对性能要求很高的程序中使用反射。

2.安全限制:

使用反射技术要求程序必须在一个没有安全限制的环境中运行。如果一个程序必须在有安全限制的环境中运行,如 Applet,那么这就是个问题了。

3.内部暴露 :

由于反射允许代码执行一些在正常情况下不被允许的操作(比如访问私有的属性和方法),所以使用反射可能会导致意料之外的副作用--代码有功能上的错误,降低可移植性。

4.反射代码破坏了抽象性:

当平台发生改变的时候,代码的行为就有可能也随着变化。

 

反射慢的原因可能有?

1.      因为接口的通用性,Java的invoke方法是传object和object[]数组的。基本类型参数需要装箱和拆箱,产生大量额外的对象和内存开销,频繁促发GC。

2.      编译器难以对动态调用的代码提前做优化,比如方法内联。

3.      反射需要按名检索类和方法,有一定的时间开销

 

 

每个.class文件被加载到内存后都是一个Class类的对象!如Demo.class加载到内存后它是Class<Demo>类型的一个对象

反射就是通过Class对象获取类型相关的信息。一个Class对象就表示一个.class文件,可以通过Class对象获取这个类的构造器、方法,以及成员变量等。

 

java.lang.reflect包下:(反射相关类)

Constructor 类 提供一个类的构造函数的信息以及访问类的构造函数的接口。

Method 类  提供一个类的方法的信息以及访问类的方法的接口。

Field 类  提供一个类的域的信息以及访问类的域的接口。

Modifier类 提供了 static 方法和常量,对类和成员访问修饰符进行解码。

Proxy 类  提供动态地生成代理类和类实例的静态方法。

Member接口 该接口可以获取有关类成员(域或者方法)后者构造函数的信息。

AccessibleObject 类 该类是域(field)对象、方法(method)对象、构造函数(constructor)对象的基础类。它提供了将反射的对象标记为在使用时取消默认 Java 语言访问控制检查的能力。

Array 类  该类提供动态地生成和访问 JAVA 数组的方法。

 

 

类装载器ClassLoader:寻找类的节码文件并构造出类在JVM内部表示对象的组件,负责在运行时查找和装入class字节码文件。类装载工作由ClassLoader以及其子类负责。

 

 

关于Class类(Java.lang.Class):

源程序通过编译(javac.exe),生成对应的.class文件,用java.exe加载(.class文件加载入内存,就是一个运行时类,放在缓存区中)每一个运行时类只加载一次

有了Class实例后,可以如下操作:

创建对应的运行时类的对象

获取对应的运行时类的完整结构(属性,方法,构造器,内部类,父类,所在的包,异常,注释。。。)

调用对应的运行时类的指定结构(属性,方法,构造器)

 

使用Class<T>的函数newInstance或Constructor对象的newInstance

 

反射的基本步骤:

1、获得Class对象,就是获取到指定的名称的字节码文件对象。

2、实例化对象,获得类的属性、方法或构造函数。

3、访问属性、调用方法、调用构造函数创建对象。

 

获取Class类的基本方式

1.通过类名称.class:(基本数据类型和引用数据类型)都有一个静态的属性class。弊端:必须要先明确该类

Class c = int.class

Class c = int[].class;

Class c = String.class

2.通过对象.getClass()方法: 弊端:必须要创建该类对象,才可以调用getClass方法

Class c = obj.getClass();

3.Class.forName()通过类名称加载类,这种方法只要有类名称就可以得到Class;扩展性最强,只要将类名字符串传入

Class c = Class.forName(“com.jinwen.Demo”);

4.包装类的方式(仅包装类):

Class<?> classtype = Boolean.TYPE; 注意:这里返回的是原生类型,和Boolean.class返回的不同

源码可知:

public static final Class<Double>   TYPE = (Class<Double>) Class.getPrimitiveClass("double");

 

5.通过类加载器加载的方式:

ClassLoader load = Thread.currentThread().getContextClassLoader();

Class clazz = loader.loadClass(“com.jinwen.Demo”);

 

根据Class创建对象的方式

1,调用空参数的构造函数:使用了Class类中的newInstance()方法。

2,调用带参数的构造函数:先要获取指定参数列表的构造函数对象,然后通过该构造函数的对象的newInstance(实际参数) 进行对象的初始化。

//获取一个带参数的构造器。

Constructor constructor = clazz.getConstructor(String.class,int.class);

 

 

Class类源码分析:

public final class Class<T> implements java.io.Serializable, GenericDeclaration, Type, AnnotatedElement {

属性:

private static final int ANNOTATION= 0x00002000;
private static final int
ENUM      = 0x00004000;
private static final int
SYNTHETIC = 0x00001000;

private transient String name;

 

static {
    registerNatives()
;
}

构造方法:

private Class(ClassLoader loader) {
   
// Initialize final field for classLoader.  The initialization value of non-null prevents future JIT optimizations from assuming this final field is null.
   
classLoader = loader;
}

forName方法:

@CallerSensitive
public static Class<?> forName(String className) throws ClassNotFoundException {
    Class<?> caller = Reflection.getCallerClass()
;
    return
forName0(className, true, ClassLoader.getClassLoader(caller), caller);
}

@CallerSensitive
public static Class<?> forName(String name, boolean initialize, ClassLoader loader)
   
throws ClassNotFoundException{
    Class<?> caller =
null;
   
SecurityManager sm = System.getSecurityManager();
    if
(sm != null) {
       
// Reflective call to get caller class is only needed if a security manager
        // is present.  Avoid the overhead of making this call otherwise.
       
caller = Reflection.getCallerClass();
        if
(sun.misc.VM.isSystemDomainLoader(loader)) {
            ClassLoader ccl = ClassLoader.getClassLoader(caller)
;
            if
(!sun.misc.VM.isSystemDomainLoader(ccl)) {
                sm.checkPermission(SecurityConstants.
GET_CLASSLOADER_PERMISSION);
           
}
        }
    }
   
return forName0(name, initialize, loader, caller);
}

private static native Class<?> forName0(String name, boolean initialize, ClassLoader loader, Class<?> caller)   throws ClassNotFoundException;

getName

获取类名称,包含包名

public String getName() {
    String name =
this.name;
    if
(name == null)
       
this.name = name = getName0();
    return
name;
}

private native String getName0();

getSimpleName

获取类名称,不包含包名

public String getSimpleName() {
   
if (isArray()) return getComponentType().getSimpleName()+"[]";
   
String simpleName = getSimpleBinaryName();
    if
(simpleName == null) { // top level class
       
simpleName = getName();
        return
simpleName.substring(simpleName.lastIndexOf(".")+1); // strip the package name
   
}
    int length = simpleName.length();
    if
(length < 1 || simpleName.charAt(0) != '$')
       
throw new InternalError("Malformed class name");
    int
index = 1;
    while
(index < length && isAsciiDigit(simpleName.charAt(index)))
        index++
;
   
// Eventually, this is the empty string iff this is an anonymous class
   
return simpleName.substring(index);
}

getSuperclass

获取父类的Class

public native Class<? super T> getSuperclass();

如:new Integer(100).getClass().getSupperClass()返回Class<Number>!但new Object().getSupperClass()返回的是null,因为Object没有父类;

newInstance:

使用本类无参构造器来创建本类对象
private volatile transient Constructor<T> cachedConstructor;

private volatile transient Class<?>       newInstanceCallerCache;

@CallerSensitive
public T newInstance() throws InstantiationException, IllegalAccessException{
   
if (System.getSecurityManager() != null) {
        checkMemberAccess(Member.
PUBLIC, Reflection.getCallerClass(), false);
   
}
   
// NOTE: the following code may not be strictly correct under the current Java memory model.
    // Constructor lookup
   
if (cachedConstructor == null) {
       
if (this == Class.class) {
          
throw new IllegalAccessException("Can not call newInstance() on the Class for java.lang.Class);
       
}
       
try {
            Class<?>[] empty = {}
;
            final
Constructor<T> c = getConstructor0(empty, Member.DECLARED);
           
// Disable accessibility checks on the constructor since we have to do the security check here anyway (the stack depth is wrong for the Constructor's security check to work)
           
java.security.AccessController.doPrivileged(
               
new java.security.PrivilegedAction<Void>() {
                    
public Void run() {
                           
c.setAccessible(true);
                            return null;
                       
}
                    })
;
           
cachedConstructor = c;
       
} catch (NoSuchMethodException e) {
            
throw (InstantiationException) new InstantiationException(getName()).initCause(e);
       
}
    }
    Constructor<
T> tmpConstructor = cachedConstructor;
   
// Security check (same as in java.lang.reflect.Constructor)
   
int modifiers = tmpConstructor.getModifiers();
    if
(!Reflection.quickCheckMemberAccess(this, modifiers)) {
        Class<?> caller = Reflection.getCallerClass()
;
        if
(newInstanceCallerCache != caller) {
            Reflection.ensureMemberAccess(caller
, this, null, modifiers);
           
newInstanceCallerCache = caller;
       
}
    }
   
// Run constructor
   
try {
       
return tmpConstructor.newInstance((Object[])null);
   
} catch (InvocationTargetException e) {
        Unsafe.getUnsafe().throwException(e.getTargetException())
;
       
// Not reached
       
return null;
   
}
}

getConstructor

通过指定的参数类型获取公有构造器反射对象

@CallerSensitive
public Constructor<T> getConstructor(Class<?>... parameterTypes)
   
throws NoSuchMethodException, SecurityException {
    checkMemberAccess(Member.
PUBLIC, Reflection.getCallerClass(), true);
    return
getConstructor0(parameterTypes, Member.PUBLIC);
}

获取所有公有构造器对象

@CallerSensitive
public Constructor<?>[] getConstructors() throws SecurityException {
    checkMemberAccess(Member.
PUBLIC, Reflection.getCallerClass(), true);
    return
copyConstructors(privateGetDeclaredConstructors(true));
}

获取所有构造器对象。包含私有构造器

@CallerSensitive
public Constructor<?>[] getDeclaredConstructors() throws SecurityException {
    checkMemberAccess(Member.
DECLARED, Reflection.getCallerClass(), true);
    return
copyConstructors(privateGetDeclaredConstructors(false));
}

通过指定参数类型获取构造器反射对象。包含私有构造器对象;

@CallerSensitive
public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
   
throws NoSuchMethodException, SecurityException {
    checkMemberAccess(Member.
DECLARED, Reflection.getCallerClass(), true);
    return
getConstructor0(parameterTypes, Member.DECLARED);
}

getField

可见 getFields 和 getDeclaredFields 区别:

getFields 返回的是申明为 public 的属性,包括父类中定义,

getDeclaredFields 返回的是指定类定义的所有定义的属性,不包括父类的

 

通过名字获取公有属性反射对象,包含父类中声明的公有属性

@CallerSensitive
public Field getField(String name)
   
throws NoSuchFieldException, SecurityException {
    checkMemberAccess(Member.
PUBLIC, Reflection.getCallerClass(), true);
   
Field field = getField0(name);
    if
(field == null) {
       
throw new NoSuchFieldException(name);
   
}
   
return field;
}

获取所有公有属性反射对象,包含父类中声明的公有属性

@CallerSensitive
public Field[] getFields() throws SecurityException {
    checkMemberAccess(Member.
PUBLIC, Reflection.getCallerClass(), true);
    return
copyFields(privateGetPublicFields(null));
}

获取本类中声明的所有属性,包含private属性,但不包含父类中声明的任何属性
@CallerSensitive

public Field[] getDeclaredFields() throws SecurityException {

    checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);

    return copyFields(privateGetDeclaredFields(false));

}

通过名字获取本类中某个属性,包含本类private属性,但父类中声明的任何属性都不包含

@CallerSensitive
public Field getDeclaredField(String name) throws NoSuchFieldException, SecurityException {
    checkMemberAccess(Member.
DECLARED, Reflection.getCallerClass(), true);
   
Field field = searchFields(privateGetDeclaredFields(false), name);
    if
(field == null) {
       
throw new NoSuchFieldException(name);
   
}
   
return field;
}

getMethod

通过方法名和方法参数类型获取公有方法反射对象,包含父类中声明的公有方法,但不包含所有私有方法

@CallerSensitive
public Method getMethod(String name, Class<?>... parameterTypes)
   
throws NoSuchMethodException, SecurityException {
    checkMemberAccess(Member.
PUBLIC, Reflection.getCallerClass(), true);
   
Method method = getMethod0(name, parameterTypes, true);
    if
(method == null) {
       
throw new NoSuchMethodException(getName() + "." + name + argumentTypesToString(parameterTypes));
   
}
   
return method;
}

获取所有公有方法,包含父类中的公有方法,但不包含任何私有方法;

@CallerSensitive
public Method[] getMethods() throws SecurityException {
    checkMemberAccess(Member.
PUBLIC, Reflection.getCallerClass(), true);
    return
copyMethods(privateGetPublicMethods());
}

通过方法名和方法参数类型获取本类中声明的所有方法的反射对象,但不包含父类中的任何方法

@CallerSensitive
public Method getDeclaredMethod(String name, Class<?>... parameterTypes)
   
throws NoSuchMethodException, SecurityException {
    checkMemberAccess(Member.
DECLARED, Reflection.getCallerClass(), true);

// privateGetDeclaredMethods方法从缓存或JVM中获取该Class中申明的方法列表,searchMethods方法将从返回的方法列表里找到一个匹配名称和参数的方法对象
    Method method = searchMethods(privateGetDeclaredMethods(false), name, parameterTypes);
    if
(method == null) {
       
throw new NoSuchMethodException(getName() + "." + name + argumentTypesToString(parameterTypes));
   
}
   
return method;
}

获取本类中所有方法,包含本类中的私有方法,但不包含父类中的任何方法。

@CallerSensitive
public Method[] getDeclaredMethods() throws SecurityException {
    checkMemberAccess(Member.
DECLARED, Reflection.getCallerClass(), true);
    return
copyMethods(privateGetDeclaredMethods(false));
}

private Method getMethod0(String name, Class<?>[] parameterTypes, boolean includeStaticMethods) {
    MethodArray interfaceCandidates =
new MethodArray(2);
   
Method res =  privateGetMethodRecursive(name, parameterTypes, includeStaticMethods, interfaceCandidates);
    if
(res != null)
       
return res;
   
// Not found on class or superclass directly
   
interfaceCandidates.removeLessSpecifics();
    return
interfaceCandidates.getFirst(); // may be null
}

缓存JVM获取Class中申明的方法列表

如果通过reflectionData()获得的ReflectionData对象不为空,则尝试从ReflectionData对象中获取declaredMethods属性,如果是第一次,或被GC回收后,重新初始化后的类属性为空,则需重新到JVM中获取一次,并赋值给ReflectionData,下次调用就可以使用缓存数据了。

private Method[] privateGetDeclaredMethods(boolean publicOnly) {
    checkInitted()
;
   
Method[] res;
   
ReflectionData<T> rd = reflectionData();  //数据结构ReflectionData,用来缓存从JVM中读取类的一些属性数据
    if (rd != null) {
        res = publicOnly ? rd.
declaredPublicMethods : rd.declaredMethods;
        if
(res != null) return res;
   
}
   
// No cached value available; request value from VM
   
res = Reflection.filterMethods(this, getDeclaredMethods0(publicOnly));
    if
(rd != null) {
       
if (publicOnly) {
            rd.
declaredPublicMethods = res;
       
} else {
            rd.
declaredMethods = res;
       
}
    }
   
return res;
}

private ReflectionData<T> reflectionData() {

// reflectionData对象是SoftReference类型的,说明在内存紧张时可能会被回收
    SoftReference<ReflectionData<T>> reflectionData = this.reflectionData;
    int
classRedefinedCount = this.classRedefinedCount;
   
ReflectionData<T> rd;
    if
(useCaches &&
        reflectionData !=
null &&
        (rd = reflectionData.get()) !=
null &&
        rd.
redefinedCount == classRedefinedCount) {
       
return rd;
   
}
   
// else no SoftReference or cleared SoftReference or stale ReflectionData
    // -> create and replace new instance
   
return newReflectionData(reflectionData, classRedefinedCount);
}

链接:主要存的是每次从jvm里获取到的一些类属性,比如方法,字段等

private static class ReflectionData<T> {

    volatile Field[] declaredFields;

    volatile Field[] publicFields;

    volatile Method[] declaredMethods;

    volatile Method[] publicMethods;

    volatile Constructor<T>[] declaredConstructors;

    volatile Constructor<T>[] publicConstructors;

    // Intermediate results for getFields and getMethods

    volatile Field[] declaredPublicFields;

    volatile Method[] declaredPublicMethods;

    volatile Class<?>[] interfaces; 

    // Value of classRedefinedCount when we created this ReflectionData instance

    final int redefinedCount;

    ReflectionData(int redefinedCount) {

        this.redefinedCount = redefinedCount;

    }

}

如果reflectionData被回收之后,又执行了反射方法,那只能通过newReflectionData方法重新创建一个这样的对象
private ReflectionData<T> newReflectionData(SoftReference<ReflectionData<T>> oldReflectionData,
                                            int
classRedefinedCount) {
   
if (!useCaches) return null;
    while
(true) {
        ReflectionData<
T> rd = new ReflectionData<>(classRedefinedCount);
       
// try to CAS it...通过使用CAS重新设置reflectionData字段;
        if (Atomic.casReflectionData(this, oldReflectionData, new SoftReference<>(rd))) {
           
return rd;
       
}
       
// else retry
       
oldReflectionData = this.reflectionData;
       
classRedefinedCount = this.classRedefinedCount;
        if
(oldReflectionData != null &&
            (rd = oldReflectionData.get()) !=
null &&
            rd.
redefinedCount == classRedefinedCount) {
           
return rd;
       
}
    }
}

 

private native Method[]      getDeclaredMethods0(boolean publicOnly);

searchMethods方法将从返回的方法列表里找到一个匹配名称和参数的方法对象

如果找到一个匹配的Method,则重新copy一份返回,即Method.copy()方法

getReflectionFactory().copyMethod(res))最终会调用Method的copy方法。所次每次调用getDeclaredMethod方法返回的Method对象其实都是一个新的对象,且新对象的root属性都指向原来的Method对象,如果需要频繁调用,最好把Method对象缓存起来

private static Method searchMethods(Method[] methods, String name, Class<?>[] parameterTypes){
    Method res =
null;
   
String internedName = name.intern();
    for
(int i = 0; i < methods.length; i++) {
        Method m = methods[i]
;
        if
(m.getName() == internedName
            && arrayContentsEq(parameterTypes
, m.getParameterTypes())
            && (res ==
null
               
|| res.getReturnType().isAssignableFrom(m.getReturnType())))
            res = m
;
   
}
   
return (res == null ? res : getReflectionFactory().copyMethod(res));
}

 

 

类类型相关方法:

boolean isArray():是否为数组类型;

boolean isAnnotation():是否为注解类型;

boolean isAnnotationPresent(Class annotationClass):当前类是否被annotationClass注解了;

boolean isEnum():是否为枚举类型;

boolean isInterface():是否为接口类型;

boolean isPrimitive():是否为基本类型;

boolean isSynthetic():是否为引用类型;

 

 

实例

String className = "cn.jinwen.com.User";

Class clazz = Class.forName(className);

User user = (User)clazz.newInstance();

System.out.println(user);

 

 

关于AccessibleObject类:

AccessibleObject类是Constructor、Method、Field三个类的父类。

当Constructor、Method、Field为私有时,如果我们想反射操作,那么就必须先调用反射对象的setAccessible(true)方法,然后才能操作。

 

AccessibleObject源码分析:

public class AccessibleObject implements AnnotatedElement {

static final private java.security.Permission ACCESS_PERMISSION =
       
new ReflectPermission("suppressAccessChecks");

setAccessible(boolean flag):

设置当前成员是否可访问
    public static void setAccessible(AccessibleObject[] array, boolean flag)
       
throws SecurityException {
        SecurityManager sm = System.getSecurityManager()
;
        if
(sm != null) sm.checkPermission(ACCESS_PERMISSION);
        for
(int i = 0; i < array.length; i++) {
            setAccessible0(array[i]
, flag);
       
}
    }

    public void setAccessible(boolean flag) throws SecurityException {
        SecurityManager sm = System.getSecurityManager()
;
        if
(sm != null) sm.checkPermission(ACCESS_PERMISSION);
       
setAccessible0(this, flag);
   
}
    private static void setAccessible0(AccessibleObject obj, boolean flag) throws SecurityException {
       
if (obj instanceof Constructor && flag == true) {
            Constructor<?> c = (Constructor<?>)obj
;
            if
(c.getDeclaringClass() == Class.class) {
               
throw new SecurityException("Cannot make a java.lang.Class constructor accessible");
           
}
        }
        obj.
override = flag;
   
}

isAccessible():

判断当前成员是否可访问
    public boolean isAccessible() {
       
return override;
   
}

构造方法

protected AccessibleObject() {}
    boolean override;
    static final ReflectionFactory reflectionFactory = AccessController.doPrivileged(
           
new sun.reflect.ReflectionFactory.GetReflectionFactoryAction());

getAnnotation

public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
       
throw new AssertionError("All subclasses should override this method");
   
}
    @Override
   
public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {
       
return AnnotatedElement.super.isAnnotationPresent(annotationClass);
   
}
    @Override
   
public <T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass) {
       
throw new AssertionError("All subclasses should override this method");
   
}
    public Annotation[] getAnnotations() {
       
return getDeclaredAnnotations();
   
}
    @Override
   
public <T extends Annotation> T getDeclaredAnnotation(Class<T> annotationClass) {
        return getAnnotation(annotationClass);
   
}
    @Override
   
public <T extends Annotation> T[] getDeclaredAnnotationsByType(Class<T> annotationClass) {
        return getAnnotationsByType(annotationClass);
   
}
    public Annotation[] getDeclaredAnnotations()  {
       
throw new AssertionError("All subclasses should override this method");
   
}

checkAccess

volatile Object securityCheckCache;
    void
checkAccess(Class<?> caller, Class<?> clazz, Object obj, int modifiers) throws IllegalAccessException {
       
if (caller == clazz) {  // quick check
           
return;             // ACCESS IS OK
       
}
        Object cache =
securityCheckCache// read volatile
       
Class<?> targetClass = clazz;
        if
(obj != null
           
&& Modifier.isProtected(modifiers)
            && ((targetClass = obj.getClass()) != clazz)) {

            if (cache instanceof Class[]) {
                Class<?>[] cache2 = (Class<?>[]) cache
;
                if
(cache2[1] == targetClass &&
                    cache2[
0] == caller) {
                   
return;     // ACCESS IS OK
               
}
            }
        }
else if (cache == caller) {
            return;             // ACCESS IS OK
       
}
        slowCheckMemberAccess(caller, clazz, obj, modifiers, targetClass);
   
}
    void slowCheckMemberAccess(Class<?> caller, Class<?> clazz, Object obj, int modifiers, Class<?> targetClass) throws IllegalAccessException {
        Reflection.ensureMemberAccess(caller
, clazz, obj, modifiers);
        Object cache = ((targetClass == clazz)? caller : new Class<?>[] { caller, targetClass });
        securityCheckCache = cache;         // write volatile
   
}
}

 

 

 

关于Constructor类(java.lang.reflect):基于JDK8

Constructor表示一个类的构造器。即构造器的反射对象

 

获取Constructor对象:

获取Construcator对象需要使用Class对象

Constructor getConstructor(Class… parameterTypes):通过指定的参数类型获取公有构造器反射对象;

Constructor[] getConstructors():获取所有公有构造器对象;

Constructor getDeclaredConstructor(Class… parameterTypes):通过指定参数类型获取构造器反射对象。可以是私有构造器对象;

Constructor[] getDeclaredConstructors():获取所有构造器对象。包含私有构造器;

 

Constructor源码分析

public final class Constructor<T> extends Executable {

属性:

private Class<T>            clazz;
private int                
slot;
private
Class<?>[]          parameterTypes;
private
Class<?>[]          exceptionTypes;
private int                
modifiers;
// Generics and annotations support
private transient String    signature;
// generic info repository; lazily initialized
private transient ConstructorRepository genericInfo;
private byte
[]              annotations;
private byte
[]              parameterAnnotations;

构造方法:

Constructor(Class<T> declaringClass, Class<?>[] parameterTypes, Class<?>[] checkedExceptions, int modifiers, int slot, String signature, byte[] annotations, byte[] parameterAnnotations) {
   
this.clazz = declaringClass;
    this
.parameterTypes = parameterTypes;
    this
.exceptionTypes = checkedExceptions;
    this
.modifiers = modifiers;
    this
.slot = slot;
    this
.signature = signature;
    this
.annotations = annotations;
    this
.parameterAnnotations = parameterAnnotations;
}

getName

获取构造器名

@Override
public String getName() {
   
return getDeclaringClass().getName();
}

getDeclaringClass

获取构造器所属的类型

@Override
public Class<T> getDeclaringClass() {
   
return clazz;
}

getParameterTypes

获取构造器的所有参数的类型

@Override
public Class<?>[] getParameterTypes() {
   
return parameterTypes.clone();   // 返回的是副本
}

@Override
public Type[] getGenericParameterTypes() {
   
return super.getGenericParameterTypes();
}

public int getParameterCount() { return parameterTypes.length; }

getExceptionTypes

获取构造器上声明的所有异常类型

@Override
public Class<?>[] getExceptionTypes() {
   
return exceptionTypes.clone();
}

@Override
public Type[] getGenericExceptionTypes() {
   
return super.getGenericExceptionTypes();
}

newInstance

通过构造器反射对象调用构造器

@CallerSensitive
public T newInstance(Object ... initargs) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{
   
if (!override) {
       
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
            Class<?> caller = Reflection.getCallerClass()
;
           
checkAccess(caller, clazz, null, modifiers);
       
}
    }
   
if ((clazz.getModifiers() & Modifier.ENUM) != 0)
       
throw new IllegalArgumentException("Cannot reflectively create enum objects");
   
ConstructorAccessor ca = constructorAccessor;   // read volatile
   
if (ca == null) {
        ca = acquireConstructorAccessor()
;
   
}
   
@SuppressWarnings("unchecked")
   
T inst = (T) ca.newInstance(initargs);
    return
inst;
}

 

 

实例:

         String className = "cn.jinwen.www.User";

         Class clazz = Class.forName(className);

         Constructor c = clazz.getConstructor(String.class, String.class);

         User user = (User)c.newInstance("zhangSan", "123");

         System.out.println(user);

 

 

关于Method类(java.lang.reflect)

 

 

获取Method:

获取Method需要通过Class对象

Method getMethod(String name, Class… parameterTypes):通过方法名和方法参数类型获取方法反射对象,包含父类中声明的公有方法,但不包含所有私有方法;

Method[] getMethods():获取所有公有方法,包含父类中的公有方法,但不包含任何私有方法;

Method getDeclaredMethod(String name, Class… parameterTypes):通过方法名和方法参数类型获取本类中声明的方法的反射对象,包含本类中的私有方法,但不包含父类中的任何方法;

Method[] getDeclaredMethods():获取本类中所有方法,包含本类中的私有方法,但不包含父类中的任何方法。

 

 

 

Method源码分析:

public final class Method extends Executable {

属性

    private Class<?>            clazz;
    private int                
slot;
   
// This is guaranteed to be interned by the VM in the 1.4
    // reflection implementation
   
private String              name;
    private
Class<?>            returnType;
    private
Class<?>[]          parameterTypes;
    private
Class<?>[]          exceptionTypes;
    private int                
modifiers;
    
// Generics and annotations support
   
private transient String              signature;
   
// generic info repository; lazily initialized
   
private transient MethodRepository genericInfo;
    private byte
[]              annotations;
    private byte
[]              parameterAnnotations;
    private byte
[]              annotationDefault;
    private volatile
MethodAccessor methodAccessor;
   
// For sharing of MethodAccessors. This branching structure is
    // currently only two levels deep (i.e., one root Method and
    // potentially many Method objects pointing to it.)
    //
    // If this branching structure would ever contain cycles, deadlocks can
    // occur in annotation code.
   
private Method              root;

构造方法

Method(Class<?> declaringClass, String name, Class<?>[] parameterTypes, Class<?> returnType, Class<?>[] checkedExceptions, int modifiers, int slot, String signature, byte[] annotations, byte[] parameterAnnotations, byte[] annotationDefault) {
   
this.clazz = declaringClass;
    this
.name = name;
    this
.parameterTypes = parameterTypes;
    this
.returnType = returnType;
    this
.exceptionTypes = checkedExceptions;
    this
.modifiers = modifiers;
    this
.slot = slot;
    this
.signature = signature;
    this
.annotations = annotations;
    this
.parameterAnnotations = parameterAnnotations;
    this
.annotationDefault = annotationDefault;
}

copy

Method copy() {

    if (this.root != null)

        throw new IllegalArgumentException("Can not copy a non-root Method");

    Method res = new Method(clazz, name, parameterTypes, returnType,

                            exceptionTypes, modifiers, slot, signature,

                            annotations, parameterAnnotations, annotationDefault);

    res.root = this;

    // Might as well eagerly propagate this if already present

    res.methodAccessor = methodAccessor;

    return res;

}

getName

获取方法名

@Override
public String getName() {
   
return name;
}

getDeclaringClass

获取方法所属的类型

@Override
public Class<?> getDeclaringClass() {
   
return clazz;
}

getParameterTypes

获取方法的所有参数的类型

@Override
public Class<?>[] getParameterTypes() {
   
return parameterTypes.clone();
}

public int getParameterCount() { return parameterTypes.length; }

@Override
public Type[] getGenericParameterTypes() {
   
return super.getGenericParameterTypes();
}

getExceptionTypes

获取方法上声明的所有异常类型

@Override
public Class<?>[] getExceptionTypes() {
   
return exceptionTypes.clone();
}

@Override
public Type[] getGenericExceptionTypes() {
   
return super.getGenericExceptionTypes();
}

getReturnType

获取方法的返回值类型

public Class<?> getReturnType() {
   
return returnType;
}

invoke

深入理解反射机制(Java)

Method 类的 invoke 方法的具体实现方式。invoke 方法内部有两种实现方式,一种是 native 原生的实现方式,一种是 Java 实现方式,这两种各有千秋。而为了最大化性能优势,JDK 源码使用了代理的设计模式去实现最大化性能

反射对象调用方法,如果当前方法是实例方法,那么当前对象就是obj,如果当前方法是static方法,那么可以给obj传递null。args表示是方法的参数

@CallerSensitive
public Object invoke(Object obj, Object... args)  throws IllegalAccessException, IllegalArgumentException, InvocationTargetException{

// 首先进行权限检查
    if (!override) {
       
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
            Class<?> caller = Reflection.getCallerClass()
;
           
checkAccess(caller, clazz, obj, modifiers);
       
}
    }
    MethodAccessor ma =
methodAccessor;             // read volatile   MethodAccessor是接口
    if (ma == null) {
        ma = acquireMethodAccessor()
;              // 反射实现,接口对应的实例类

  }

// 最后调用了 MethodAccessor 接口的实现类的 invoke 方法进行进一步处理
    return ma.invoke(obj, args);
}

关于MethodAccessor接口(sun.reflect):

MethodAccessor 是一个接口,定义了方法调用的具体操作、

public interface MethodAccessor {
    Object invoke(Object obj
, Object[] args) throws IllegalArgumentException, InvocationTargetException;
}

MethodAccessor有三个具体的实现类:

sun.reflect.DelegatingMethodAccessorImpl:最终注入给MethodmethodAccessor的,也就是某个Method的所有的invoke方法都会调用到这个DelegatingMethodAccessorImpl.invoke,正如其名一样的,是做代理的

sun.reflect.MethodAccessorImpl:实现主要是native实现的,而GeneratedMethodAccessorXXX是为每个需要反射调用的Method动态生成的类,后的XXX是一个数字,不断递增的,且所有的方法反射都是先走NativeMethodAccessorImpl,默认调了15次之后,才生成一个GeneratedMethodAccessorXXX类,生成好之后就会走这个生成的类的invoke方法了

sun.reflect.NativeMethodAccessorImpl:

 

MethodAccessor 对象其实就是具体去生成反射类的入口

查看MethodAccessor源码上的注释,我们可以了解到 MethodAccessor 对象的一些设计信息。

"Inflation" mechanism. Loading bytecodes to implement Method.invoke() and Constructor.newInstance() currently costs 3-4x more than an invocation via native code for the first invocation (though subsequent invocations have been benchmarked to be over 20x faster).Unfortunately this cost increases startup time for certain applications that use reflection intensively (but only once per class) to bootstrap themselves.

Inflation 机制。初次加载字节码实现反射,使用 Method.invoke() 和 Constructor.newInstance() 加载花费的时间是使用原生代码加载花费时间的 3 - 4 倍。这使得那些频繁使用反射的应用需要花费更长的启动时间

To avoid this penalty we reuse the existing JVM entry points for the first few invocations of Methods and Constructors and then switch to the bytecode-based implementations. Package-private to be accessible to NativeMethodAccessorImpl and NativeConstructorAccessorImpl.

为了避免这种痛苦的加载时间,我们在第一次加载的时候重用了 JVM 的入口,之后切换到字节码实现的实现。

 

实际的 MethodAccessor 实现有两个版本,一个是 Native 版本,一个是 Java 版本。

Native 版本一开始启动快,但是随着运行时间边长,速度变慢。Java 版本一开始加载慢,但是随着运行时间边长,速度变快。正是因为两种存在这些问题,所以第一次加载的时候我们会发现使用的是 NativeMethodAccessorImpl 的实现,而当反射调用次数超过 15 次之后,则使用 MethodAccessorGenerator 生成的 MethodAccessorImpl 对象去实现反射

// 返回MethodAccessor接口的实现类(通过工厂类实现)

先判断是否存在对应的 MethodAccessor 对象,如果存在那么就复用之前的 MethodAccessor 对象,否则调用 ReflectionFactory 对象的 newMethodAccessor 方法生成一个 MethodAccessor 对象。

private MethodAccessor acquireMethodAccessor() {
   
// First check to see if one has been created yet, and take it
    // if so
   
MethodAccessor tmp = null;
    if
(root != null) tmp = root.getMethodAccessor();
    if
(tmp != null) {
       
methodAccessor = tmp;
   
} else {
       
// Otherwise fabricate one and propagate it up to the root
       
tmp = reflectionFactory.newMethodAccessor(this);   // ReflectionFactory工厂实例化一个实现MethodAccessor接口的对象
        setMethodAccessor(tmp);
   
}
   
return tmp;
}

ReflectionFactory工厂类

深入理解反射机制(Java)

在 ReflectionFactory 类的 newMethodAccessor 方法里,首先生成一个 NativeMethodAccessorImpl 对象,再这个对象作为参数调用 DelegatingMethodAccessorImpl 类的构造方法。

这里使用代理模式,将 NativeMethodAccessorImpl 对象交给 DelegatingMethodAccessorImpl 对象代理。

ReflectionFactory 类的 newMethodAccessor 方法最终返回 DelegatingMethodAccessorImpl 类对象。

 

在ReflectionFactory类中,有2个重要的字段:noInflation(默认false)和inflationThreshold(默认15),在checkInitted方法中可以通过-Dsun.reflect.inflationThreshold=xxx和-Dsun.reflect.noInflation=true对这两个字段重新设置,而且只会设置一次;

如果noInflation为false,方法newMethodAccessor都会返回DelegatingMethodAccessorImpl对象:

深入理解反射机制(Java)

DelegatingMethodAccessorImpl对象就是一个代理对象,负责调用被代理对象delegate的invoke方法,其中delegate参数目前是NativeMethodAccessorImpl对象,所以最终Method的invoke方法调用的是NativeMethodAccessorImpl对象invoke方法,实现如下:

深入理解反射机制(Java)

而在 NativeMethodAccessorImpl 的 invoke 方法里,其会判断调用次数是否超过阀值(numInvocations)。如果超过该阀值,就生成另一个MethodAccessor 对象,并将原来 DelegatingMethodAccessorImpl 对象中的 delegate 属性指向最新的 MethodAccessor 对象。

这里用ReflectionFactory类中的inflationThreshold,当delegate调用了15次invoke方法后,如果继续调用就通过MethodAccessorGenerator类的generateMethod方法生成MethodAccessorImpl对象,并设置为delegate对象,这样下次执行Method.invoke时,就调用新建的MethodAccessor对象的invoke()方法

 

注:

generateMethod方法在生成MethodAccessorImpl对象时,会在内存中生成对应的字节码,并调用ClassDefiner.defineClass创建对应的class对象

深入理解反射机制(Java)

在ClassDefiner.defineClass方法实现中,每被调用一次都会生成一个DelegatingClassLoader类加载器对象

深入理解反射机制(Java)

每次都生成新的类加载器,是为了性能考虑,在某些情况下可以卸载这些生成的类,因为类的卸载是只有在类加载器可以被回收的情况下才会被回收的,如果用了原来的类加载器,那可能导致这些新创建的类一直无法被卸载,从其设计来看本身就不希望这些类一直存在内存里的,在需要的时候有就行了。

 

Q:并发导致垃圾类创建

NativeMethodAccessorImpl.invoke都是不加锁的,意味着如果并发很高时,可能同时有很多线程进入到创建GeneratedMethodAccessorXXX类的逻辑里,虽然说最终使用的其实只会有一个,但是这些开销已然存在了,假如有1000个线程都进入到创建GeneratedMethodAccessorXXX的逻辑里,那意味着多创建了999个无用的类,这些类会一直占着内存,直到能回收Perm的GC发生才会回收

 

 

实例

         Class clazz = Person.class;

         Method method = clazz.getMethod(methodName, new Class[]{paramClazz1, paramClazz2});

         method.invoke();

 

关于Field类(java.lang.reflect)

ield表示类的成员变量,可以是实例变量,也可以是静态变量。

获取Field对象:

获取Field对象需要使用Class对象,下面是Class类的API:

Field getField(String name):通过名字获取公有成员变量的反射对象,包含父类中声明的公有成员变量;

Field[] getFields():获取所有公有成员变量反射对象,包含父类中声明的公有成员变量;

Field getDeclaredField(String name):通过名字获取本类中某个成员变量,包含本类的private成员变量,但父类中声明的任何成员变量都不包含;

Field[] getDeclaredFields():获取本类中声明的所有成员变量,包含private成员变量,但不包含父类中声明的任何成员变量;

 

 

 

Field类源码分析

public final class Field extends AccessibleObject implements Member {

属性:

private Class<?>            clazz;
private int                
slot;
// This is guaranteed to be interned by the VM in the 1.4
// reflection implementation

private String              name;
private
Class<?>            type;
private int                
modifiers;
// Generics and annotations support
private transient String    signature;
// generic info repository; lazily initialized
private transient FieldRepository genericInfo;
private byte
[]              annotations;
// Cached field accessor created without override
private FieldAccessor fieldAccessor;
// Cached field accessor created with override
private FieldAccessor overrideFieldAccessor;
// For sharing of FieldAccessors. This branching structure is
// currently only two levels deep (i.e., one root Field and
// potentially many Field objects pointing to it.)
//
// If this branching structure would ever contain cycles, deadlocks can
// occur in annotation code.

private Field               root;

构造方法:

Field(Class<?> declaringClass, String name, Class<?> type, int modifiers, int slot, String signature, byte[] annotations){
   
this.clazz = declaringClass;
    this
.name = name;
    this
.type = type;
    this
.modifiers = modifiers;
    this
.slot = slot;
    this
.signature = signature;
    this
.annotations = annotations;
}

 

getName():

获取成员变量名;

public String getName() {
   
return name;
}

getDeclaringClass():

获取成员变量的类型;

public Class<?> getDeclaringClass() {
   
return clazz;
}

getType():

获取当前成员变量的类型;

public Class<?> getType() {

    return type;

}

public Type getGenericType() {
   
if (getGenericSignature() != null)
       
return getGenericInfo().getGenericType();
    else
        return
getType();
}

get(Object obj):

获取obj对象的成员变量的值;

@CallerSensitive

public Object get(Object obj) throws IllegalArgumentException, IllegalAccessException{

    if (!override) {

        if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {

            Class<?> caller = Reflection.getCallerClass();

            checkAccess(caller, clazz, obj, modifiers);

        }

    }

    return getFieldAccessor(obj).get(obj);

}
// 还有其他类型的,包括BooleanByteCharShortIntegerFloatLongDouble

@CallerSensitive

public boolean getBoolean(Object obj) throws IllegalArgumentException, IllegalAccessException{  
    if (!override) {

        if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {

            Class<?> caller = Reflection.getCallerClass();

            checkAccess(caller, clazz, obj, modifiers);

        }

    }

    return getFieldAccessor(obj).getBoolean(obj);  // 仅此处不同

}

set(Object obj, Object value):

设置obj对象的成员变量值为value;

@CallerSensitive
public void set(Object obj, Object value) throws IllegalArgumentException, IllegalAccessException{
   
if (!override) {
       
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
            Class<?> caller = Reflection.getCallerClass()
;
           
checkAccess(caller, clazz, obj, modifiers);
       
}
    }
    getFieldAccessor(obj).set(obj
, value);
}

@CallerSensitive
public void setBoolean(Object obj, boolean z) throws IllegalArgumentException, IllegalAccessException{
   
if (!override) {
       
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
            Class<?> caller = Reflection.getCallerClass()
;
           
checkAccess(caller, clazz, obj, modifiers);
        
}
    }
    getFieldAccessor(obj).setBoolean(obj
, z);
}

getAnnotation

public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
    Objects.requireNonNull(annotationClass)
;
    return
annotationClass.cast(declaredAnnotations().get(annotationClass));
}

@Override
public <T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass) {
    Objects.requireNonNull(annotationClass)
;
    return
AnnotationSupport.getDirectlyAndIndirectlyPresent(declaredAnnotations(), annotationClass);
}

public Annotation[] getDeclaredAnnotations()  {
   
return AnnotationParser.toArray(declaredAnnotations());
}

private native byte[] getTypeAnnotationBytes0();

public AnnotatedType getAnnotatedType() {
   
return TypeAnnotationParser.buildAnnotatedType(getTypeAnnotationBytes0(),

sun.misc.SharedSecrets.getJavaLangAccess().getConstantPool(getDeclaringClass()),this, getDeclaringClass(),getGenericType(),TypeAnnotation.TypeAnnotationTarget.FIELD);

 

实例:

Protected和private都需要setAccessible(true),否则将抛异常

         Field field = clazz.getField(fieldName);

         field.setAccessible(true);

         field.setObject(value);

 

用反射获取泛型信息

为了通过反射操作泛型以迎合实际开发的需要, Java新增了java.lang.reflect.ParameterizedType java.lang.reflect.GenericArrayTypejava.lang.reflect.TypeVariable java.lang.reflect.WildcardType几种类型来代表不能归一到Class类型但是又和原始类型同样重要的类型.

类型

含义

ParameterizedType

一种参数化类型, 比如Collection<String>

GenericArrayType

一种元素类型是参数化类型或者类型变量的数组类型

TypeVariable

各种类型变量的公共接口

WildcardType

一种通配符类型表达式, 如? ? extends Number ? super Integer

用ParameterizedType来获取泛型信息.

public class Client {

    private Map<String, Object> objectMap;

    public void test(Map<String, User> map, String string) {

    }

    public Map<User, Bean> test() {

        return null;

    }

    /**

     * 测试属性类型

     */

    @Test

    public void testFieldType() throws NoSuchFieldException {

        Field field = Client.class.getDeclaredField("objectMap");

        Type gType = field.getGenericType();

        // 打印type与generic type的区别

        System.out.println(field.getType());

        System.out.println(gType);

        System.out.println("**************");

        if (gType instanceof ParameterizedType) {

            ParameterizedType pType = (ParameterizedType) gType;

            Type[] types = pType.getActualTypeArguments();

            for (Type type : types) {

                System.out.println(type.toString());

            }

        }

    }

    /**

     * 测试参数类型

     */

    @Test

    public void testParamType() throws NoSuchMethodException {

        Method testMethod = Client.class.getMethod("test", Map.class, String.class);

        Type[] parameterTypes = testMethod.getGenericParameterTypes();

        for (Type type : parameterTypes) {

            System.out.println("type -> " + type);

            if (type instanceof ParameterizedType) {

                Type[] actualTypes = ((ParameterizedType) type).getActualTypeArguments();

                for (Type actualType : actualTypes) {

                    System.out.println("\tactual type -> " + actualType);

                }

            }

        }

    }

    /**

     * 测试返回值类型

     */

    @Test

    public void testReturnType() throws NoSuchMethodException {

        Method testMethod = Client.class.getMethod("test");

        Type returnType = testMethod.getGenericReturnType();

        System.out.println("return type -> " + returnType);

        if (returnType instanceof ParameterizedType) {

            Type[] actualTypes = ((ParameterizedType) returnType).getActualTypeArguments();

            for (Type actualType : actualTypes) {

                System.out.println("\tactual type -> " + actualType);

            }

        }

    }

用反射获取注解

 

 

动态代理:(见动态代理)

主要涉及的类为java.lang.reflect包中的两个接口,Proxy和InvocationHandler。

 

类的生命周期 (见JVM)

 

 

 

反射在工厂模式:

interface fruit{

    public abstract void eat();

}

class Apple implements fruit{

    public void eat(){

        System.out.println("Apple");

    }

}

class Orange implements fruit{

    public void eat(){

        System.out.println("Orange");

    }

}

// 构造工厂类

// 也就是说以后如果我们在添加其他的实例的时候只需要修改工厂类就行了

class Factory{

    public static fruit getInstance(String fruitName){

        fruit f=null;

        if("Apple".equals(fruitName)){

            f=new Apple();

        }

        if("Orange".equals(fruitName)){

            f=new Orange();

        }

        return f;

    }

}

class hello{

    public static void main(String[] a){

        fruit f=Factory.getInstance("Orange");

        f.eat();

    }

}

使用反射的工厂模式:

interfacefruit{

    public abstract void eat();

}

classAppleimplementsfruit{

    publicvoideat(){

        System.out.println("Apple");

    }

}

  

classOrangeimplementsfruit{

    publicvoideat(){

        System.out.println("Orange");

    }

}

  

classFactory{

    publicstaticfruit getInstance(String ClassName){

        fruit f=null;

        try{

            f=(fruit)Class.forName(ClassName).newInstance();

        }catch(Exception e) {

            e.printStackTrace();

        }

        returnf;

    }

}

classhello{

    publicstaticvoidmain(String[] a){

        fruit f=Factory.getInstance("Reflect.Apple");

        if(f!=null){

            f.eat();

        }

    }

}

 

 

相关链接:

1.你假笨:从一起GC血案谈到反射原理

「深入Java」类型信息:RTTI和反射