APP下载

当Jvm遇到new关键字

消息来源:baojiabao.com 作者: 发布时间:2024-05-16

报价宝综合消息当Jvm遇到new关键字

在上一篇我们知道了Jvm的内存划分,这一篇我们来具体分析一下,当我们用new关键字建立一个新物件时,Jvm都做了哪些工作。当虚拟机器执行到new指令时,发现它是关键字,于是会检查这个指令引数是否能在常量池中找到相关的引用,并检查这个引用所代表的类是否被载入、解析和初始化过。如果没有被载入,则先执行类的载入过程。当类载入成功后,虚拟机器就会为新建立的物件分配内存。分配内存无非就是在Java堆上划出一部分割槽域来作为新物件的储存空间。但在实际的处理时是比较麻烦的。例如怎么找到空闲的内存,如何划分固定大小内存。我们知道Java虚拟机器规范中所说虚拟机器中的堆内存可以是连续的也可以是不连续的。所以虚拟机器在为物件分配新内存时,就要根据这两种不同的方式来采取不同的实现。这两种方式分别叫作:指标碰撞和空闲列表。正面我们分别看一下它们具体的实现方式。

指标碰撞:所谓的连续内存是指Java堆中的内存是绝对规整的,用过的内存在一边,空闲的内存在另一边。中间有个指标作为分界点,这时如果要分配新内存,只要指标向空闲的内存一方移动一下就可以了。这种分配内存的方式就叫指标碰撞。空闲列表:如果Java堆中的内存并不是完整的,也就是不是连续的。这时使用的内存和空闲的内存没有任何规则,无法用指标碰撞的方式,来分配内存。这时虚拟机器只能采取其它办法来标识出哪些内存是使用的,哪些内存是空闲的,所以虚拟机器就要维护一个列表,用来储存哪些内存是空闲的,分配内存时,只要从列表中划分一块区域储存物件例项,并更新列表上的记录就可以了。这种方式就叫空闲列表。由于不同的虚拟机器所采用的内存分配方式是不同的,所以上述主要说明两种分配内存的方式,虚拟机器到底采用哪种方式由不同虚拟机器的堆自行决定。

上述的过程只是给物件分配了相关的内存空间,但物件还是空的,内存资料要怎么储存物件的资讯呢?在虚拟机器中物件在内存中储存主要分3个区域:

物件头:主要包括两部分一个是物件自己的执行资料如杂凑码、GC分代年龄、锁状态标识、执行绪持有的锁、偏向执行绪ID等官方称知为Mark Word。物件头的另一部分就是型别指标,也就是物件指向类元资料的指标,虚拟机器通过这个指标确定这个物件是哪个类的例项。物件头的资讯是不固定的,如果物件是一个数组,那么在物件头中就会有记录阵列长度的资讯。

例项资料:也就是程式中自定义的各种字段的型别和内容,包括父类或子类的资料都在这里储存,这是物件真正的储存的有效资讯。对齐填充:主要的作是就是占位符。因为虚拟机器要求物件起始地址必须是8字节的整数倍也就是物件大小必须是8的整数倍,因此,如果物件的例项资料没有对齐时,就会需要通过对齐填充来补齐。物件现在已经建立完了,但它是储存在堆上的,为了方便我们操作堆中的物件,Java是通过栈上的引用资料来操作堆上的具体物件的。这个引用是使用直接指标访问的。堆中要储存这个指标的相关资讯,而引用储存的就是该物件的内存地址。

以上就是在建立一个新物件时Jvm对内存的主要操作。因为不同的虚拟机器可能有不同的处理逻辑,上述中所描述的虚拟机器都指的是Sun HotSpot虚拟机器。

2019-10-26 09:57:00

相关文章