Class类源码

反射

Posted by chchaooo on February 23, 2019
public final class Class<T> implements java.io.Serializable,
                              GenericDeclaration,
                              Type,
                              AnnotatedElement {
    /** defining class loader, or null for the "bootstrap" system loader. */
    private transient ClassLoader classLoader;
    
    /** The superclass, or null if this is java.lang.Object, an interface or primitive type. */
    private transient Class<? super T> superClass;
    
    /**
     * Virtual method table (vtable), for use by "invoke-virtual". The vtable from the superclass
     * is copied in, and virtual methods from our class either replace those from the super or are
     * appended. For abstract classes, methods may be created in the vtable that aren't in
     * virtual_ methods_ for miranda methods.
     */
    private transient Object vtable;
    
    /**
     * Instance fields. These describe the layout of the contents of an Object. Note that only the
     * fields directly declared by this class are listed in iFields; fields declared by a
     * superclass are listed in the superclass's Class.iFields.
     *
     * All instance fields that refer to objects are guaranteed to be at the beginning of the field
     * list.  {@link Class#numReferenceInstanceFields} specifies the number of reference fields.
     */
    private transient long iFields;

    /** All methods with this class as the base for virtual dispatch. */
    private transient long methods;

    /** Static fields */
    private transient long sFields;

    /** access flags; low 16 bits are defined by VM spec */
    private transient int accessFlags;

    /** Class flags to help the GC with object scanning. */
    private transient int classFlags;

    /**
     * Total size of the Class instance; used when allocating storage on GC heap.
     * See also {@link Class#objectSize}.
     */
    private transient int classSize;

    /**
     * tid used to check for recursive static initializer invocation.
     */
    private transient int clinitThreadId;
    
    

Class类里面的属性看起来都比较熟悉。

/*
 * Private constructor. Only the Java Virtual Machine creates Class objects.
 * This constructor is not used and prevents the default constructor being
 * generated.
 */
private Class() {}

Class has no public constructor. Instead Class objects are constructed automatically by the Java Virtual Machine as classes are loaded and by calls to the defineClass method in the class loader.

Class没有公开的构造器。当类需要被使用是,虚拟机会自动创建Class实例。此外classloader中的defineClass方法也也可以创建Class实例。

@CallerSensitive
public static Class<?> forName(String className) throws ClassNotFoundException {
    return forName(className, true, VMStack.getCallingClassLoader());
}

forName方法使用当前类的classloader来进行类加载

    /**
     * Note that this method does not check whether the requested class
     * is accessible to its caller.
     */
    @CallerSensitive
    public static Class<?> forName(String name, boolean initialize ClassLoader loader)
        throws ClassNotFoundException
    {
        if (loader == null) {
            loader = BootClassLoader.getInstance();
        }
        Class<?> result;
        try {
            result = classForName(name, initialize, loader);
        } catch (ClassNotFoundException e) {
            Throwable cause = e.getCause();
            if (cause instanceof LinkageError) {
                throw (LinkageError) cause;
            }
            throw e;
        }
        return result;
    }

    /** Called after security checks have been made. */
    @FastNative
    static native Class<?> classForName(String className, boolean shouldInitialize,
            ClassLoader classLoader) throws ClassNotFoundException;

实际的由className到Class的转换是在native层做的。调用之前的逻辑主要是:确定classloader,如果传入的classloader为空,那么久设置为BootClassLoader。注意注释中特别注明的,这里并不检查调用者是否拥有对目标className对应类的访问权限。

    @CallerSensitive
    public Field[] getFields() throws SecurityException {
        List<Field> fields = new ArrayList<Field>();
        getPublicFieldsRecursive(fields);
        return fields.toArray(new Field[fields.size()]);
    }

    /**
     * Populates {@code result} with public fields defined by this class, its
     * superclasses, and all implemented interfaces.
     */
    private void getPublicFieldsRecursive(List<Field> result) {
        // search superclasses
        for (Class<?> c = this; c != null; c = c.superClass) {
            Collections.addAll(result, c.getPublicDeclaredFields());
        }

        // search iftable which has a flattened and uniqued list of interfaces
        Object[] iftable = ifTable;
        if (iftable != null) {
            for (int i = 0; i < iftable.length; i += 2) {
                Collections.addAll(result, ((Class<?>) iftable[i]).getPublicDeclaredFields());
            }
        }
    }

获取所有field:

  1. 递归查找自己以及parent中的公开fields
  2. 查找所有接口中的fields
    public Method getMethod(String name, Class<?>... parameterTypes)
        throws NoSuchMethodException, SecurityException {
        return getMethod(name, parameterTypes, true);
    }

    public Method getDeclaredMethod(String name, Class<?>... parameterTypes)
        throws NoSuchMethodException, SecurityException {
        return getMethod(name, parameterTypes, false);
    }

    private Method getMethod(String name, Class<?>[] parameterTypes, boolean recursivePublicMethods)
            throws NoSuchMethodException {
        if (name == null) {
            throw new NullPointerException("name == null");
        }
        if (parameterTypes == null) {
            parameterTypes = EmptyArray.CLASS;
        }
        for (Class<?> c : parameterTypes) {
            if (c == null) {
                throw new NoSuchMethodException("parameter type is null");
            }
        }
        Method result = recursivePublicMethods ? getPublicMethodRecursive(name, parameterTypes)
                                               : getDeclaredMethodInternal(name, parameterTypes);
        // Fail if we didn't find the method or it was expected to be public.
        if (result == null ||
            (recursivePublicMethods && !Modifier.isPublic(result.getAccessFlags()))) {
            throw new NoSuchMethodException(name + " " + Arrays.toString(parameterTypes));
        }
        return result;
    }
    
    private Method getPublicMethodRecursive(String name, Class<?>[] parameterTypes) {
        // search superclasses
        for (Class<?> c = this; c != null; c = c.getSuperclass()) {
            Method result = c.getDeclaredMethodInternal(name, parameterTypes);
            if (result != null && Modifier.isPublic(result.getAccessFlags())) {
                return result;
            }
        }

        return findInterfaceMethod(name, parameterTypes);
    }
    
    @FastNative
    private native Method getDeclaredMethodInternal(String name, Class<?>[] args);

与查找method有关的方法,可以看以下几个点:

  1. getMethod递归获取该类以及其父类中的所有public方法
  2. getDeclaredMethod是非递归查找,只查找当前类中的方法(非public方法也会返回)
  3. getDeclaredMethodInternal实际查找当前类中方法,但是这个代码又是native的

思考

综合看下来,一个最大的问题是,private和public的方法这个都很好理解,但是对于protected和包访问权限的方法,class类里面的方法是如何处理的?