class加载到运行时数据区前的加载过程:
- 通过一个类的全限定名来获取定义的class二进制字节流。
- 通过类加载器,加载此文件。从下往上依次为User Defined Class Loader、Application Class Loader、Extension Class Loader、BootStrap Class Loader(自定义类加载器 -> 应用类加载器 -> 扩展类加载器 -> 扩展类加载器 -> 引导类加载器)
- 连接-验证(文件格式校验)
- 将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构
- 连接-验证 (元数据验证、字节码验证)
- 在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据的访问入口
- 链接-准备,会为类变量初始化默认变量值,但并不会分配初始化实例对象(final static不包括在内)
- 链接-解析,将常量池中的符号引用转换为直接引用、就是HelloWorld.class反编译中反编译代码Constant pool中的信息。
- 链接-验证 (符号引用验证)
- 初始化,始化阶段就是执行类构造器()方法的过程
类加载器:
启动类加载器( 引导类加载器,Bootstrap ClassLoader )
- 加载Java的核心库(JAVA_HOME / jre / lib / rt.jar、resources.jar 或 sun.boot.class.path 路径下的内容)
- 为了安全,Bootstrap启动类加载器只加载包名为java、javax、sun等开头的类
扩展类加载器(Extension ClassLoader)
- JDK安装目录 jre / lib / ext子目录(扩展目录)下加载类库
应用程序类加载器(系统类加载器,AppClassLoader)
- 该类加载是程序中默认的类加载器,一般来说,Java应用的类都是由它来完成加载的
双亲委派:
按需将class文件加载到内存够中,子类加载器会将子类请求委托给父类加载,如果父类加载器可以完成类加载任务,就成功返回,并且子类不再进行加载。如果父类加载器无法完成此加载任务,子加载器才会尝试自己去加载,若果子类也无法加载,抛出ClassNotFoundException异常。
- 意义:防止类重复加载,加重安全防护,防止核心API修改
- 注: 当编译器成功后,运行期找不到此类(可能被删除、也可能被篡改)则抛出NoClassDefFoundError异常