深入理解HotSpot虚拟机

一、对象创建过程
当虚拟机遇到一条new 指令时,便会进行对象的创建过程。

创建对象的过程如下:
1.检查常量池中有没有这个类的符号引用,并且检查这个符号引用代表的类有没有被虚拟机加载过。
如果没有被加载过,则执行类加载过程,然后进入下一步;
如果已加载,则进入下一步。
2.根据方法区中类的信息,在堆区划分一块确定大小的内存给对象。
(经过类加载后,类的信息被保存在方法区中,一个类的对象所需的内存大小也固定下来。)
3.为对象的成员变量赋初始值
内存分配完成之后,需要对分配的内存空间部分区域的内容都初始化为零值。
这一步保证了对象成员变量在java代码中可以不赋初始值。
4.设置对象头中的信息
关于对象头是什么, 别急,继续往下看。
5.调用方法进行初始化
别再问是什么了,先往下看。

二、问题解惑:
在堆区分配内存有两种方式。

指针碰撞法
如果堆中内存是规整的,即所有用过的内存都放在一边,空闲的内存放在另一边,中间用一个指针做分界点的指示器。

分配内存的过程,实际上就是指针向空闲空间那边移动一段与对象大小相等的距离。

空闲列表法
java堆中的内存如果不是规整的,就需要使用空闲列表的分配方式。

空闲列表概念:虚拟机维护了一个列表,用于记录哪些内存块是可用的。

在分配的时候,从列表中找到一块满足对象大小的内存空间划分给对象实例,同时会更新列表上的记录。

关于两种分配方式的选择
选择哪种分配方式取决于java堆是否规整。

而java堆是否规整取决于所采用的垃圾收集器是否带有压缩整理的功能。

因此,选择哪种分配方式最终取决于使用了哪种垃圾收集器。

使用了指针碰撞的垃圾收集器有哪些?
serial、ParNew等基于复制算法或标记整理(Mark Compact)算法的收集器,不会导致内存碎片,因此使用的是指针碰撞。

采用空闲链表垃圾收集器有哪些?
CMS等基于Mark-Sweep(标记清除)算法的收集器,会产生内存碎片,所以使用空闲列表法。

猜你喜欢

转载自blog.csdn.net/yangguang330/article/details/83317023