类加载器
引导类加载器
- 引导类装入器是用本地代码实现的类装入器,它负责将 <Java_Runtime_Home>/lib下面的核心类库或-Xbootclasspath选项指定的jar包加载到内存中。
- 由于引导类加载器涉及到虚拟机本地实现细节,开发者无法直接获取到启动类加载器的引用,所以不允许直接通过引用进行操作
扩展类加载器
- 负责将< Java_Runtime_Home >/lib/ext或者由系统变量-Djava.ext.dir指定位置中的类库加载到内存中。
应用类加载器
- 负责将系统类路径java -classpath或-Djava.class.path变量所指的目录下的类库加载到内存中。
类加载的过程
loading(加载)
- 通过类的全限定名,获取此类的二进制流
- 将二进制流代表的静态的数据存储结构转换为运行时数据结构
- 在内存中生成一个代表此类的java.lang.class文件,作为方法区此类各种数据的访问入口
linking(连接)
verify(验证)
- 验证的作用: 确保class文件中包含的信息符合《java虚拟机规范》的全部约束,保证这些信息作为代码运行时不会危害到虚拟机本身。
- 文件格式验证: 验证字节流是否符合class文件格式的规范,并且能被当前版本的虚拟机处理。
prepare(准备)
- 为类变量分配内存空间,并默认赋值。
1) 不包含被final修饰的类变量(此类的变量在编译期间就会分配内存空间)
resolve(解析)
- 将常量池内的符号引用转换为直接引用的过程。
initialization(初始化)
- 初始化其实就是执行类构造器方法()的过程。
1)方法不需要定义,是javac编译器自动收集类中所有类变量的赋值和静态代码块中的语句合并而来的
2)构造器方法中指令的执行顺序是按照代码的顺序执行。
3)在加载子类的方法时,必须保证父类的方法已经被加载。
4)类的构造器方法只会被执行一次,所以虚拟机在执行类构造器方法()时,在多线程下必须同步加锁。
双亲委派机制
- 如果一个类加载器收到了类加载请求,它不会自己先去加载,而是把这个请求委托给父类的加载器去执行。
- 如果父类加载器还存在其父类加载器,则进一步向上委托,依次递归请求最终到达启动类加载器。
- 如果父类加载器可以完成类加载任务,就成功返回。如果父类加载器无法完成此加载任务,则子类加载器才会尝试自己加载。