JVM之类加载过程

大家好,我是骄阳

今天我们来聊一下jvm类加载过程。

之前我都是直接背这个面试问题的八股文,然后面试的时候装作不是提前背好的,循序渐进地说出来,但我发现,背完很容易忘,而且我根本禁不住面试官问,他随便延伸一点我就答不上来

主要原因还是因为我没有理解它。

那么首先什么是类加载?

其实就是从我们写出来的.java文件到被程序使用的整个过程

总共分为七步

1 加载:

2 验证:

3 准备:

4 解析:

5 初始化:

6 使用

7 卸载

package mysqltest; 
public class Math { 

public static final int initData = 666; 
public static final Object obj = new Object(); 

public int compute() { 
//一个方法对应一块栈帧内存区域 
int a = 1; int b = 2; 
int c = (a + b) * 10; 
return c; 

}
 public static void main(String[] args) {
 Math math = new Math(); 
math.compute(); 
} }

1 加载:

定义:

在硬盘上查找class文件,并通过IO流读取字节码文件。

注意:

jvm是懒加载,所以只有使用到类时才会加载,例如调用类的main()方法,new对象等等 ,主类在运行过程中如果使用到其它类,会逐步加载这些类。在加载阶段会在内存中生成一个代表这个类的java.lang.Class对象,作为这个类的各种数据的访问入口

为什么是懒加载的?

其实也很容易想明白的,jar包或war包里的类可能上万个,肯定不是一次性全部加载进来,不然启动太慢了。

2 验证:

校验字节码文件的正确性

比如开头是否是cafe babe,这是约定俗成的。

一个class文件的16进制大体结构如下图:

对应的含义如下,细节可以查下oracle官方文档

3 准备:

给类的静态变量分配内存,并赋予默认值,比如int类型的值默认为0

4 解析:

将符号引用替换为直接引用。

那么什么是符号引用?

拓展:字面量(Literal)和符号引用(Symbolic References)

Class文件中除了包含类的版本、字段、方法、接口等描述信息外,还有一项信息就是常量池(constant pool table),用于存放编译期生成的各种字面量(Literal)和符号引用(Symbolic References)。

一个class文件的16进制大体结构如下图:

当然我们一般不会去人工解析这种16进制的字节码文件,我们一般可以通过javap命令生成更可读的JVM字节码指令文件:

javap -v Math.class

红色标出的就是class常量池信息,常量池中主要存放两大类常量:字面量和符号引用。

字面量

字面量就是指由字母、数字等构成的字符串或者数值常量

字面量只可以右值出现,所谓右值是指等号右边的值。

如:int a=1 这里的a为左值,1为右值。在这个例子中1就是字面量。

int a = 1; int b = 2; int c = "abcdefg"; int d = "abcdefg";

符号引用

符号引用是编译原理中的概念,是相对于直接引用来说的。主要包括了以下三类常量:

  • 类和接口的全限定名 
  • 字段的名称和描述符 
  • 方法的名称和描述符

上面的a,b就是字段名称,就是一种符号引用,还有Math类的全限定名,main和compute是方法名称,()是一种UTF8格式的描述符,这些都是符号引用。

刚才我们讲清楚了字面量和符号引用,那么什么是直接引用?将符号引用替换为直接引用,又是什么样的过程?

简单来说就是,obj这个符号引用在运行时就会被转变为obj具体代码在内存中的地址

我们来详细说下

我们知道我们写的每一行代码最终都要加载到内存里,那么内存那么大,这个obj 变量到底放在哪里,是不是会有一个内存地址来标识,如果我们用一个指针指向这个内存地址,这个指针就是直接引用。

等我们需要用到这个变量的时候,就可以直接通过指针指向的地址找到。

而我们在加载类的时候,解析 obj这段代码并指向内存某个地址,然后将符号引用 obj和这个内存地址进行映射的过程,就是解析这个步骤要做的事,也叫做符号引用转换为直接引用。

整个过程主要通过对象头里的类型指针去转换直接引用。

同时这个过程,也就是我们通常说的静态链接。

既然提到了静态链接,那么和它成对出现的动态链接又是什么?

其实本质都是一样的

只不过动态链接是类加载期间不进行指向,程序运行期间再指向。

和静态链接的区别就是进行指向的时间不同。

5 初始化:

(1)对类的静态变量初始化为指定的值

int initData = 666

(2)执行静态代码块

6 使用

7 卸载

好啦,这就是今天全部的内容,喜欢我的话,可以点个关注支持一下~

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值