深入理解JVM之类加载机制

类加载机制

在了解类加载之前我们先来了解一下我们所写的Java代码如何进行工作,我们编写的.java文件经过javac编译后形成.class文件,.class文件再被加载到内存中进行运行。下面先来看看.class(类)文件中都有哪些内容。

.class(类)文件的结构

在类文件开头首先会有4个字节的魔数,它的功能主要是用来确定该文件是否能够被JVM接受。接下来会有一系列的版本信息,包括第5、6个字节代表的次版本号,第7、8个字节代表的主版本号。接下来分别是常量池表、访问标志、索引(包括类索引、父索引、接口索引)集合、字段表集合、方法表集合、属性表集合。

类的生命周期

在这里插入图片描述
当遇到一下四种情况是必须立刻对类进行初始化操作:

  1. 通过new关键字实例化类的对象、调用类的静态方法、get/set类的静态变量;
  2. 使用反射机制对类进行反射调用时;
  3. 当初始化一个类时如果其父类未被初始化,需要先初始化其父类
  4. 虚拟机启动时,主类(即包含main方法的类)需要被初始化

类的加载过程

类的加载过程也就是上图中的加载、验证、准备、连接、初始化五个步骤。

加载

加载阶段(注意此处的加载是类加载过程中的一个步骤,而不是只类加载)主要完成三个任务

  1. 根据类的权限定名获取指定的二进制流;
  2. 将类文件中的静态存储结构转换为方法区中的运行时存储结构;
  3. 在堆中创建代表该类对应的java.lang.Class对象。

验证

验证阶段主要是为了确保输入的类文件的字节流满足JVM的要求,避免其对JVM造成损害。虽然编译器会帮JVM拒绝一些不安全的代码,比如数组越界、对象类型的错误转换等,但是输入的字节流并不一定都是经过编译得来的,所以存在一定威胁。验证阶段主要包括下面四个过程

  1. 文件格式验证
  2. 元数据验证
  3. 字节码验证
  4. 符号引用验证

准备

准备阶段会对类变量进行内存分配并设置初始值(这里需要注意的是,在准备阶段设置的初始值并非代码中设置的初始值,二是系统默认的零值,这一点用过C++的或许较为熟悉,变量没有赋值时系统会给它自动设置一个初始值)。

解析

解析阶段主要是将常量池中的符号引用转化为直接引用。这里来简单说一下符号引用和直接引用,符号引用就是指用一个符号来指定引用的目标,只要在使用时能够保证无歧义的找到即可(可以理解为符号引用是我去找我的导师,但我并不关心他在哪,当我真正去找的时候我才需要知道他在哪个办公室)。直接引用可以使直接指向引用目标的指针、句柄或者相对偏移量。(此时我就需要知道导师办公室在哪个楼,门牌号是多少了)。

类加载器

类加载器可以分为:启动类加载器、扩展类加载器、应用类加载器以及用户自定义的类加载器
在这里插入图片描述
这里提一下类的双亲委派机制,即当一个类需要被加载时,不会立刻调用该类的加载器,而是向上找其父类加载器,知道找到最顶部的启动类加载器;如果父类不能够完成加载任务在向下依次找子类加载器完成加载。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值