java中的类加载机制,ClassLoader是如何查找类的?

类似问法:描述一下 JVM 加载 class 文件的原理机制?

参考解答

1. 类加载的概念

类加载器(ClassLoader)是一组特殊的类,负责在运行时查找和加载其他类。

java中的类加载器分四个层次:

英文 中文 搜索路径
Bootstrap ClassLoader 系统类加载器 JAVA_HOME/lib/rt.jar
Extension ClassLoader 扩展类加载器 JAVA_HOME/lib/ext/*.jar
App ClassLoader 应用程序类加载器 ClassPath
Custom ClassLoader 自定义类加载器 自定义

为了称呼方便把它们分别称为 BC, EC, AC, CC

如果定义了一个自己的类加载器:

ClassLoader cc = new ClassLoader() {
    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        // 具体的加载类操作
    }
};

cc.loadClass("java.lang.String"); // 情况1
cc.loadClass("entity.User");      // 情况2,User类在ClassPath上
cc.loadClass("enitty.Order");     // 情况3,Order类不在ClassPath上

工作流程为:

情况1: 希望通过cc加载java.lang.String类,这时cc会询问它的父亲ac看看这个类是否已经被加载,ac会询问它的父亲ec看看这个类是否已经被加载,最后ec去询问bc看这个类是否被加载。

java.lang.String类位于rt.jar包中,它会被bc所加载,因此再向下通知ec,ac,cc该类已经加载过了,这时cc中提供的findClass方法不会被调用。

情况2: 希望通过cc加载entity.User类,这时cc会询问它的父亲ac看看这个类是否已经被加载,ac会询问它的父亲ec看看这个类是否已经被加载,最后ec去询问bc看这个类是否被加载。

bc发现这个类没有被加载,但它只负责rt.jar中的类加载,因此将通知ec来加载这个类,ec只负责加载lib/ext/*.jar,因此又把加载委托给ac来完成,最后ac在ClassPath上找到了entity.User类,加载成功。 同样cc提供的findClass方法没必要调用了。

情况3: 希望通过cc加载entity.Order类,这时cc会询问它的父亲ac看看这个类是否已经被加载,ac会询问它的父亲ec看看这个类是否已经被加载,最后ec去询问bc看这个类是否被加载。

bc发现这个类没有被加载,但它只负责rt.jar中的类加载,因此将通知ec来加载这个类,ec只负责加载lib/ext/*.jar,因此又把加载委托给ac来完成,ac只负责ClassPath路径上的类加载,因此将加载委托给cc。 最后由cc调用findClass方法完成类加载。

2. 类加载的阶段

类加载分为3个阶段:硬加载、链接、初始化

硬加载(physical loading) 就是将*.class的字节码读取至内存的过程,但这个阶段,被加载类有哪些方法,引用了哪些其它类,有哪些属性,这些都还是未知的。

链接(linking) 这个阶段要完成字节码的校验、建立被加载类的基本内存结构(例如给静态变量分配空间)、以及解析操作(将符号引用转换为直接引用)。

初始化(initializing) 这个阶段执行静态变量的赋值,静态代码块中的代码。

3. 类加载中的重要方法

类加载是通过 ClassLoader类加载器来完成的,其中重要方法有:

  • loadClass(String name) 是根据类名称加载类,完成加载阶段的操作,只会涉及前两个阶段,不会执行初始化阶段
  • findClass(String name) 是提供给自定义类加载器的一种扩展方式,自定义类加载器会优先使用父类类加载器和系统类加载器来加载类,如果它们俩无法找到类时,最后会调用自定义类加载器的findClass方法来加载类
  • defineClass(String name,byte[] bin,int offset, int limit) 是当类的字节码来源不是classpath上的文件时(例如,通过其它如网络、字节码生成技术生成的代表了类字节码的byte[]),可以调用此方法来完成加载类的工作。但它不应当被直接调用,一般是通过findClass间接调用

results matching ""

    No results matching ""