JVM内存模型-3

48 阅读2分钟

「这是我参与2022首次更文挑战的第17天,活动详情查看:2022首次更文挑战」。

对象的访问/定位

我们Java程序员常说的对象引用,就是通过虚拟机栈中reference数据来定位堆内存中的对象。因为JVM规范中并没有指定这个引用通过什么方式去实现,所以目前定位方式大致分为两种:

1.句柄

在这里插入图片描述

2.直接引用

在这里插入图片描述 目前HotSpot虚拟机默认采用直接引用方式,更加方便。但是并不代表句柄方式不适合,句柄也有很大的好处,就是句柄存储的是稳定的句柄地址,当对象被移动的时候不需要修改栈中的数据(垃圾收集会涉及对象地址的移动)。而使用直接引用方式最大的好处就是访问速度更快,节省了一步寻址的时间开销。

对象的创建和内存分配

在这里插入图片描述 对象的创建分为两种模式:1.指针碰撞。2.空闲列表。

1.指针碰撞

如果堆内存中的空闲内存是绝对整齐的(用的的内存放一边,空闲的放另一边),此时JVM在创建对象分配内存的时候只需要把指针向空闲的区域移动指定大小(对象的大小在类加载的时候已经可以确定,且是8字节的整数倍大小)。这种分配方式称之为指针碰撞在这里插入图片描述

2.空闲列表

空闲列表相对于指针碰撞要复杂很多,如果堆内存中可用内存不是整齐的那么就不能使用指针碰撞这种方式,那就JVM就需要额外维护一个数据池,用来记录内存中哪些地址是可用的内存。当分配的时候从数据池中找出足够的空间用来分配对象,并且更新数据池里的数据记录,这种分配方式称之为空闲列表

那么问题来了,JVM到底选择哪种模式进行的对象分配呢?

选择哪种方式是由堆内存的整齐度决定,而内存的整齐度取决于采用的是哪种GC收集器是否带有空间压缩整理功能决定。当使用Serial、Paraller Scavenge、ParNew等收集器时系统采用指针碰撞,如果使用CMS收集器只能用空闲列表方式。每种垃圾收集器的区别之后解答。