类加载子系统的作用:
将所需要的Class文件进行加载,加载流程存在一下几个阶段:
- 第一个阶段为加载阶段(Loading阶段):这个阶段是将引导类加载器和非引导类加载器需要加载的Class文件进行加载。
具体来说:
- 引导类加载器(BootStrapClassLoader):这个加载器的作用是将java_home/jre/lib下的Class文件进行加载,它是由C、C++语言编写的,通过getClassLoader().parent()的方式进行获取的结果为null
- 非引导类加载器:也就是通过Java代码编写的类加载器(继承java.lang.ClassLoader),它有三部分:
- 扩展类加载器(Extension ClassLoader):这是引导类加载器之后的第二优先级的加载器,通常负责加载Java的扩展库,也就是位于JDK的jre/lib/ext目录下或者由系统变量java.ext.dirs指定的路径下的类或包。
- 应用类加载器(Application ClassLoader):也称为系统类加载器,这是ClassLoader层次结构中的第三级,它负责加载CLASSPATH上指定的类库。它是Java应用程序默认使用的类加载器。
- 用户自定义类加载器(Custom ClassLoader):用户可以创建自己的类加载器,这些类加载器一般继承自ClassLoader类或其子类,以实现特殊的类加载逻辑,比如从特定的存储介质(网络、加密文件等)加载类和资源。
(注意哈,它们之间的关系是层级关系,类似于文件夹,引导>拓展>引用>自定义)
说到类加载器就涉及到了双亲委派机制:
什么是双亲委派机制:简单来说就是在加载一个Class文件的时候都会寻找上级,看上级是否能加载这个Class文件,如果所有的上级都不行,才轮到自己加载
为什么要使用这种机制:使用这种机制就可以解决类重复加载问题,也可以为Java的核心类如String呀起一个保护作用
2.第二个阶段为连接阶段(Linking阶段):Linking阶段分为三个阶段,分别为
- 校验阶段(Verify):他的作用是确保加载的Class文件是合法的,是否符合Java虚拟机的规划要求,具体分为
- 格式校验:验证Class文件结构是否正确,例如字节码文件是不是以CAFEBABE开头等
- 安全校验:验证Class文件是否对虚拟机产生危害等等
...
- 准备阶段(Perpare):这个阶段的作用是为类中的类变量(静态变量)在方法区(元空间)分配内存并赋默认值,这里需要注意,如果是static修饰并且用final修饰的变量会在分配了内存之后直接赋值(因为final修饰的变量不能进行修改,所以就在分配内存之后就进行赋值)
- 解析阶段(Resolve):它的主要作用是将常量池(Constant Pool)中的符号引用转化为直接引用(内存地址),这里可以通过javap -v xxx.class 文件将class文件转化为字节码之后进行观察Constant Pool部分。
3.第三个阶段为初始化阶段(Initialization阶段):将准备阶段中的静态变量进行赋值,执行静态代码块(执行clinit部分)