JVM类加载机制

什么是类加载?

类加载指的是在JVM虚拟机中使用ClassLoader把“.class”字节码文件转成二进制文件流存储在内存存,然后通过加载——验证——准备——解析——初始化,使得文件转换成可以调用的java.lang

.Class对象。

类加载的阶段

类加载通常分为五个阶段:

加载:将.class字节码转成二进制字节流,将字节流表示的静态存储结构转为metaspace元空间的运行时存储结构,然后在内存中生成一个代表该类的Class对象。

验证:为了防止危害到虚拟机的安全,通常类加载会验证字节码文件:通过对于文件格式验证, 元数据验证,字节码验证,符号引用验证来防止恶意加载。

准备:类变量一般是static的成员变量,所以该阶段会对变量分配内存,但不会赋值,通常是null或者0。

解析:把常量池的符号引用转换为直接引用。

初始化:这时候正式执行Java代码的初始化方法,根据方法对变量进行赋值,不过需要注意的是,静态代码块需要调用静态成员变量时,需要定义在成员变量后面,因为<clinit>()是根据编译器自动收集类中的变量赋值动作和静态语句块中的语句结合产生的,不能读取语句块之后定义的静态变量,只能修改变量,不能使用。

类加载的时机

分为主动引用和被动引用

主动引用:

  • 当一个接口中定义了 JDK8 新加入的默认方法(被 default 关键字修饰的接口方法)时,如果有这个接口的实现类发生了加载,则该接口要在实现类之前被加载;
  • 当调用指令码例如:new,putstatic,getstatic,invokestatic,会加载类;
  • 当虚拟机启动,包含main()函数的类会被优先加载;
  • 当单独调用子类不调用父类时,会优先加载父类;
  • 当使用反射时,调用newInstance以及Class.forname会进行类加载;
  • 当加载一个类时,若其父类尚未被加载,则会优先加载父类;
  • 当一个类中包含主函数main(),则会优先被加载;
  • 当一个接口中定义了 JDK8的default方法,若这个接口实现类的该方法被加载了,则会优先加载该接口。

被动引用:

  • 当调用类中的常量时,不会加载该类;
  • 通过子类访问父类的静态字段,不会加载父类;
  • 当把类对象当作数组初始化时,不会加载类。会将其当作数组类加载。

类加载器

启动类加载器:使用C++编译,无法直接操作,记加载Java的一些基本库;

扩展类加载器:扩展类库大多数类由扩展类加载器加载,例如js引擎、xml解析器等;

应用程序加载器:用于加载用户自定义的类或者第三方jar包;

双亲委派模型

什么是双亲委派模型?

在Java中类加载时,为了保证每个类只被加载一次(不引起歧义),类加载机制中采用了双亲委派模型。它的作用就是防止同一个类被多次加载。

实现思想是什么?

类加载器在需要加载类时,优先转发给父加载器,当父加载器无法加载时,才由当前加载器加载。

双亲委派模型的作用?

保证每个类只被加载一次,解决了各个类加载器加载基础类的统一问题;

防止出现恶意加载,内存中不会出现多个一样的字节码文件,保障程序稳定运行。

对象的创建过程

类加载检查:虚拟机遇到一条 new 指令时,首先将去检查这个指令的参数是否能在常量池中定位到这个类的符号引用,并且检查这个符号引用代表的类是否已被加载过、解析和初始化过。如果没有,那必须先执行相应的类加载过程。

分配内存:在类加载检查通过后,接下来虚拟机将为新生对象分配内存。对象所需的内存大小在类加载完成后便可确定,为对象分配空间的任务等同于把一块确定大小的内存从 Java 堆中划分出来。内存分配的查找方式有 “指针碰撞” 和 “空闲列表” 两种。

初始化零值:内存分配完成后,虚拟机需要将分配到的内存空间都初始化为零值(不包括对象头),这一步操作保证了对象的实例字段在 Java代码中可以不赋初始值就直接使用,程序能访问到这些字段的数据类型所对应的零值。

设置对象头:初始化零值完成之后,虚拟机要对对象进行必要的设置,例如这个对象是哪个类的实例、如何才能找到类的元数据信息、对象的哈希码、对象的 GC 分代年龄等信息。 这些信息存放在对象头中。 另外,根据虚拟机当前运行状态的不同,如是否启用偏向锁等,对象头会有不同的设置方式。

执行init()构造方法:在上面工作都完成之后,从虚拟机的视角来看,一个新的对象已经产生了,但从Java 程序的视角来看,对象创建才刚开始,<init> 构造方法还没有执行,目前所有的字段都还为零。所以一般来说,执行 new 指令之后会接着执行 <init> 构造方法,把对象按照程序逻辑的意愿进行初始化,这样一个真正可用的对象才算完整创建出来。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值