#二、类加载器的介绍之前也提到了它是负责加载.class文件的,它们在文件开头会有特定的文件标示,将class文件字节码内容加载到内存中,并将这些内容转换成方法区中的运行时数据结构,并且ClassLoader只负责class文件的加载,而是否能够运行则由 Execution Engine 来决定
#2.1 类加载器的流程从类被加载到虚拟机内存中开始,到释放内存总共有7个步骤:加载,验证,准备,解析,初始化,使用,卸载 。其中验证,准备,解析三个部分统称为连接
#2.1.1 加载
- 将class文件加载到内存
- 将静态数据结构转化成方法区中运行时的数据结构
- 在堆中生成一个代表这个类的 java.lang.Class对象作为数据访问的入口
- 验证:确保加载的类符合 JVM 规范和安全,保证被校验类的方法在运行时不会做出危害虚拟机的事件,其实就是一个安全检查
- 准备:为static变量在方法区中分配内存空间,设置变量的初始值,例如 static int a = 3 (注意:准备阶段只设置类中的静态变量(方法区中),不包括实例变量(堆内存中),实例变量是对象初始化时赋值的)
- 解析:虚拟机将常量池内的符号引用替换为直接引用的过程(符号引用比如我现在import java.util.ArrayList这就算符号引用,直接引用就是指针或者对象地址,注意引用对象一定是在内存进行)
注意:字节码文件中初始化方法有两种,非静态资源初始化的<init>和静态资源初始化的<clinit>,类构造器方法<clinit>()不同于类的构造器,这些方法都是字节码文件中只能给JVM识别的特殊方法 。#2.1.4 卸载GC将无用对象从内存中卸载
#2.2 类加载器的加载顺序加载一个Class类的顺序也是有优先级的,类加载器从最底层开始往上的顺序是这样的
- BootStrap ClassLoader:rt.jar
- Extension ClassLoader: 加载扩展的jar包
- App ClassLoader:指定的classpath下面的jar包
- Custom ClassLoader:自定义的类加载器
这样做的好处是,加载位于 rt.jar 包中的类时不管是哪个加载器加载,最终都会委托到 BootStrap ClassLoader 进行加载,这样保证了使用不同的类加载器得到的都是同一个结果 。
其实这个也是一个隔离的作用,避免了我们的代码影响了 JDK 的代码,比如我现在自己定义一个 java.lang.String :
package java.lang;public class String {public static void main(String[] args) {System.out.println();}}
尝试运行当前类的 main 函数的时候,我们的代码肯定会报错 。这是因为在加载的时候其实是找到了 rt.jar 中的java.lang.String,然而发现这个里面并没有 main 方法 。#三、运行时数据区#3.1 本地方法栈和程序计数器比如说我们现在点开Thread类的源码,会看到它的start0方法带有一个native关键字修饰,而且不存在方法体,这种用native修饰的方法就是本地方法,这是使用C来实现的,然后一般这些方法都会放到一个叫做本地方法栈的区域 。
程序计数器其实就是一个指针,它指向了我们程序中下一句需要执行的指令,它也是内存区域中唯一一个不会出现OutOfMemoryError的区域,而且占用内存空间小到基本可以忽略不计 。这个内存仅代表当前线程所执行的字节码的行号指示器,字节码解析器通过改变这个计数器的值选取下一条需要执行的字节码指令 。
如果执行的是native方法,那这个指针就不工作了 。
推荐阅读
- 二维码的升级版「三维码」你使用过吗?
- 保证健康的宝贵食物你掌握几种
- 开车那么久,你知道该如何保养爱车吗?
- 平板支撑有多厉害?坚持做一个月你就知道了
- 如果你正准备换发型,别错过这30款
- 蚊子最爱叮什么血型的人,你知道吗?
- 揠苗助长的意思和寓意 拔苗助长告诉我们什么道理
- 见男友的小tips是什么梗 见男友的小tips
- 中考成绩怎么查?
- 小叶紫檀|木质界的帝王之木,你了解多少?