类加载机制

类加载机制

1. 类的加载

类加载是指将类的class文件读入内存,并为之创建一个java.lang.Class对象。

2. 类的连接

类连接分为三个阶段:
1. 验证:用于检验被加载的类是否具有正确的内部结构
2. 准备:负责为类的类变量分配内存,并设置默认初始值
3. 解析:将类的二进制数据中的符号引用替换为直接引用

3. 类的初始化

  • 主要是对类变量进行初始化
  • 类初始化的时机(6种)
    1. 创建类的实例,比如使用new操作符来创建实例,通过反射来创建实例,通过反序列化来创建实例
    2. 调用某个类的类方法
    3. 调用某个类的类变量或为该类变量赋值
    4. 使用反射方式创建某个类对应的java.lang.Class对象,比如Class.forName("person"),注意ClassLoader类的loadClass()方法只是加载某个类,并不会执行初始化
    5. 初始化某个类的子类
    6. 使用java.exe来运行某个主类

4. 类加载器

在java中,采用全限定名(包名和类名)作为一个类的标识,但在JVM中,采用全限定名和其加载器作为其唯一标识。

  • Bootstrap ClassLoader 根类加载器
  • Extension ClassLoader 扩展类加载器
  • App ClassLoader 应用类加载器

根类加载器主要用来加载java的核心类库(比如rt.jar, charsets.jar, resources.jar),由JVM自身实现。

扩展类加载器负责加载JRE的扩展目录(jre/lib/ext或者java.ext.dirs系统属性指定的目录)中的JAR包

系统类加载器负责在JVM启动时加载 -classpath 或java.class.path系统属性或CLASSPATH环境变量所指定的JAR包和类路径;

5. 类加载机制

  • 全盘负责 就是当一个类加载器负责加载某个类时,该Class所依赖和引用的其他Class也将由该类加载器负责载入, 除非显示指定使用另外一个类加载器来载入
  • 父类委托 则是先让父类加载器试图加载该Class, 只有在父类加载器无法加载该类时才尝试从自己的类路径中加载该类 (层次结构:根类加载器->扩展类加载器->应用类加载器->用户类加载器)
  • 缓存机制 缓存机制会保存加载过的Class

加载代码

//去掉了部分
protected Class<?> loadClass(String name, boolean resolve)
        throws ClassNotFoundException
    {
        synchronized (getClassLoadingLock(name)) {
           // First, check if the class has already been loaded
            Class<?> c = findLoadedClass(name);
            if (c == null) {
                try {
                    if (parent != null) {
                        c = parent.loadClass(name, false);
                    } else {
                        c = findBootstrapClassOrNull(name);
                    }
                } catch (ClassNotFoundException e) {
                  // ClassNotFoundException thrown if class not found
                  // from the non-null parent class loader
                }

                if (c == null) {
                // If still not found, then invoke findClass in order
                    // to find the class.
                    c = findClass(name); //注意
                    //findClass根据指定名称查找类
                }
            }
            if (resolve) {
                resolveClass(c);
            }
            return c;
        }
    }

//defineClass 负责将指定将类的字节码文件转换成Class对象
//用户自定义类加载器通过集成ClassLoader,并重写findClass方法
//URLClassLoader功能很强大,可以从本地文件系统中读取二进制文件来加载类
//也可以从远程主机中读取二进制文件来加载类

你可能感兴趣的:(类加载)