java.lang.ClassLoader与java.net.URLClassLoader学习

第一部分:java.lang.ClassLoader

类加载器(class loader)用来加载 Java 类到 Java 虚拟机中。一般来说,Java 虚拟机使用 Java 类的方式如下:Java 源程序(.java 文件)在经过 Java 编译器编译之后就被转换成 Java 字节代码(.class 文件)。类加载器负责读取 Java 字节代码,并转换成 java.lang.Class 类的一个实例。每个这样的实例用来表示一个 Java 类。通过此实例的 newInstance()方法就可以创建出该类的一个对象。实际的情况可能更加复杂,比如 Java 字节代码可能是通过工具动态生成的,也可能是通过网络下载的。 基本上所有的类加载器都是 java.lang.ClassLoader 类的一个实例

  1. 构造函数

public abstract class ClassLoader
   
private static native void registerNatives();
    static {
        registerNatives();
    }
    
private ClassLoader(Void unused, ClassLoader parent) {
        this.parent = parent;
        if (ParallelLoaders.isRegistered(this.getClass())) {
            parallelLockMap = new ConcurrentHashMap<>();
            package2certs = new ConcurrentHashMap<>();
            domains =
                Collections.synchronizedSet(new HashSet<ProtectionDomain>());
            assertionLock = new Object();
        } else {
            // no finer-grained lock; lock on the classloader instance
            parallelLockMap = null;
            package2certs = new Hashtable<>();
            domains = new HashSet<>();
            assertionLock = this;
        }
    }


2.loadClass方法,该方法为类加载器的主要方法,具体代码如下:


    

 protected Class<?> loadClass(String name, boolean resolve)
        throws ClassNotFoundException
    {
            //1.异步保护,防止重复加载同一个class
        synchronized (getClassLoadingLock(name)) {
            //2.首先,检查是否类已经被加载过了
            Class<?> c = findLoadedClass(name);
            if (c == null) {
            //2.1如果该类未被加载过
                    //2.1.1 System.nanoTime()这个方法主要是返回一个系统计时器的当前值,以毫微秒为单位。但是不能用作来计算当前时间,只能通过end-start算出间隔时间
                long t0 = System.nanoTime();
                try {
                    if (parent != null) {
                    //2.1.2如果有父加载器,即父加载器不为初始加载器,则递归父加载器查看是否加载过
                        c = parent.loadClass(name, false);
                    } else {
                    //2.1.3如果没有父加载器,即父加载器为初始加载器,查找类是否加载,具体看方法
                        c = findBootstrapClassOrNull(name);
                    }
                } catch (ClassNotFoundException e) {
                    // ClassNotFoundException thrown if class not found
                    // from the non-null parent class loader
                }

                if (c == null) {
                    //2.1.4如果还是没有该类,则运行findClass方法加载,该方法为虚方法
                    long t1 = System.nanoTime();
                    c = findClass(name);

                    // this is the defining class loader; record the stats
                    sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
                    sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
                    sun.misc.PerfCounter.getFindClasses().increment();
                }
            }
            if (resolve) {
            //解析class,resolve默认为false
                resolveClass(c);
            }
            return c;
        }
    }


3.getClassLoadingLock(name)方法

 protected Object getClassLoadingLock(String className) {
        Object lock = this;
        if (parallelLockMap != null) {
            Object newLock = new Object();
            lock = parallelLockMap.putIfAbsent(className, newLock);
            if (lock == null) {
                lock = newLock;
            }
        }
        return lock;
    }




4.findLoadedClass(name)方法

   protected final Class<?> findLoadedClass(String name) {
        if (!checkName(name))
            return null;
        return findLoadedClass0(name);
    }

    private native final Class<?> findLoadedClass0(String name);


5.findBootstrapClassOrNull(name)方法

 private Class<?> findBootstrapClassOrNull(String name)
    {
        if (!checkName(name)) return null;

        return findBootstrapClass(name);
    }

    // return null if not found
    private native Class<?> findBootstrapClass(String name);


6.findClass(name)方法,该方法在ClassLoader中没有具体实现,因此根据不同的情况会重写该方法进行不同情况的判断。

 protected Class<?> findClass(String name) throws ClassNotFoundException {
        throw new ClassNotFoundException(name);
    }

7.resolveClass(Class<?> c)方法

 protected final void resolveClass(Class<?> c) {
        resolveClass0(c);
    }

    private native void resolveClass0(Class<?> c);

8.defineClass方法,主要是将字节码class文件进行实例为Class实例。该方法不可覆盖,我们在继承ClassLoader的时候,会重写findClass方法将相关文件转换成jvm可识别的Class实例。必须要在重写的findClass中调用defineClass才可以完成转换的逻辑。

    

protected final Class<?> defineClass(String name, byte[] b, int off, int len)
        throws ClassFormatError
    {
        return defineClass(name, b, off, len, null);
    }
 protected final Class<?> defineClass(String name, byte[] b, int off, int len,
                                         ProtectionDomain protectionDomain)
        throws ClassFormatError
    {
        protectionDomain = preDefineClass(name, protectionDomain);
        String source = defineClassSourceLocation(protectionDomain);
        Class<?> c = defineClass1(name, b, off, len, protectionDomain, source);
        postDefineClass(c, protectionDomain);
        return c;
    }

9.ClassLoader类的相关测试。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章