什么是类加载器?
Java类加载器是Java运行时环境的一部分,负责动态加载Java类到Java虚拟机的内存空间中。
上图,
类加载器子系统作用:类加载器子系统负责从文件系统或者网络中加载Class文件;类加载器只负责Class文件的加载,至于可否运行,则由Execution Engine决定;加载的类信息存放于方法区内。
类加载器流程:加载——链接(验证-准备-解析)——初始化
加载阶段:
(1)通过一个类的全限定名获取定义此类的二进制字节流
(2)将字节流所代表的静态存储结构转化为方法区的运行时数据结构
(3)在内存中生成一个代表该类的java.lang.Class对象,作为方法区中对于这个类的各种数据的访问入口
验证阶段:确保Class文件的字节流中包含的信息符合当前虚拟机要求,保证被加载的类的正确性,不会损害虚拟机安全。
准备阶段:为类变量(静态成员变量)分配内存(方法区),设置初始值。(不包括final修饰的类变量)
解析阶段:将常量池内的符号引用转换为直接引用的过程。
注:在编译时每个java类都会被编译为一个class文件,但在编译的时候虚拟机并不会知道所引用类的地址,用符号引用来代替,在解析时则将这个符号引用转换为真正的地址
初始化阶段:执行类构造器方法<clinit>()</clinit>的过程
注:
①该方法不需要定义,是javac编译器自动收集类中的所有类变量的赋值动作和静态代码块合并。
②该方法的指令按照语句在源文件中的出现顺序执行。
③该方法不同于类构造器<init></init>。
④若有父类,JVM保证在子类<clinit></clinit>执行前,父类的已经执行完。
⑤JVM保证一个类的<clinit></clinit>方法在多线程下同步加锁。
类加载器分类:
引导类加载器/启动类加载器(Bootstrap ClassLoader);自定义类加载器(User-Defined ClassLoader)
自定义类加载器:将所有派生于抽象类ClassLoader的类加载器都划分为自定义类加载器。
包括:Extension ClassLoader(扩展类加载器),App ClassLoader(应用类加载器/系统类加载器),Custom ClassLoader(自定义类加载器)
注:BootstrapClassLoader是用C、C++语言写的,其余是用Java语言写的。没有继承ClassLoader
引导类加载器:用来加载Java的核心库,用于提供JVM自身需要的类。出于安全考虑,Bootstrap只加载包为java、javax、sun等开头的类。
扩展类加载器:从java.ext.dirs系统属性所指定的目录中加载类库,或从JDK的安全目录的jre/lib/ext子目录(扩展目录)下加载类库,如果用户创建的JAR放在此目录下,也会自动由扩展类加载器加载。
系统类加载器:加载环境变量CLASSPATH或系统属性java.class.path指定路径下的类库,一般而言,项目中自己写的类由该加载器加载。
双亲委派机制:
作用(1)避免类的重复加载(2)保护程序安全,防止核心API被随意篡改