类加载过程(7步)
加载
通过类的加载器,使用类的完全限定名,查找和导入class文件,加载到内存中;
验证
验证载入的class文件数据的正确性,是否符合JVM规则;
准备
为类静态变量(static)分配内存并设置类静态变量初始值阶段;(实例变量会在对象实例化时随对象一块分配在Java堆中)
解析
虚拟机将常量池内的符号引用(指通过一组符号来描述目标)替换为直接引用的过程;也就是得到类或字段、方法在内存中的指针或偏移量。
- 引用替换;字段解析;接口解析;方法解析;
初始化
完成类静态变量(static)的赋值和静态代码块(static)执行(只有主动调用时才初始化);
- 初始化一个类,其父类未初始化,则向触发该父类的初始化。
- 使用java.lang.reflect 包的方法对类进行反射时(如:Class.forName("...").newInstance()),如果类未初始化,需先初始化。
使用
对象实例化;
卸载:
GC垃圾回收,将无用对象从内存中卸载。
- 在JVM生命周期中,由JDK自带的类加载器负责加载的JDK提供的类,是不会被回收的。自定义的类加载的实例是可以被回收的。
类加载器(ClassLoader)
四种类加载器
- BootstrapClassLoader(启动类加载器):负责加载核心Java库(加载JAVA_HOME/jre/lib中的类)。启动类加载器无法被Java程序直接使用。它是所有类加载器的父加载器。
- ExtensionClassLoader(扩展类加载器):负责加载Java的扩展库(加载JAVA_HOME/jre/ext/*.jar中的类)。
- AppClassLoader(应用程序类加载器):负责加载当前应用classpath下的所有jar包和类。
- CustomClassLoader(自定义类加载器):可以通过继承java.lang.ClassLoader来实现。
- 双亲委派机制
- 类加载时,系统会首先判断当前类是否被加载过。是,则被加载的类直接返回;否则,才会尝试加载。
- 加载器加载类时,先把请求委托给自身的父类加载器执行;如果父类加载器还存在其父类的加载器,则进一步向上委托,一直递归,直到请求到达顶层的启动类加载器。只有当父类加载器无法完成这个类加载请求时,才会让子类加载器去处理这个请求。
- 当父类加载器为null时,会使用启动类加载器BootstrapClassloader作为父类加载器。
- 优点:
- 保证了Java程序的稳定运行,可以避免类的重复加载;
- 保证了Java的核心API不被篡改。