JMM——对象的创建、内存布局及访问
讲解HotSpot虚拟机在Java堆中对象分配、布局和访问的全过程
以某大厂面试题展开对象的内存布局问题
1、请解释以下对象的创建过程?
2、对象在内存中的存储布局?
3、对象头具体包括什么?
4、对象怎么定位?
5、对象怎么分配?
6、Object o = new Object在内存中占用几个字节?
一、请解释以下对象的创建过程?
这个问题其实就是问:new了一个对象,在本质上是怎样一个过程
大致可分为以下步骤
1、检查符号引用
当JVM遇到字节码new指令的时候,将去检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并且检查这个符号引用所代表的类是否被加载、解析和初始化过
如果没有加载过则先执行相应的类加载过程,在前面我们详细讲过类加载过程,这里简单回忆:
1、Class Loading
类加载、类加载器、双亲委派模型
2、Class Linking
1、验证——Verification
2、准备——Preparation(半初始化,类变量赋零值(默认值))
3、解析——Resolution
3、Class Initializing
初始化过程——对上面赋零值的类变量,按照程序员的设置赋初始值
上面的过程,是如果Class还没有Load到内存,上面三步就是完成类加载load过程。如果已经Load到内存,就不会再次执行上面的步骤。
2、申请对象内存
上面的类加载通过之后,接下来就是虚拟机为新生对象分配内存。
对象所需的内存大小在类加载完成之后便可以完全确定,为对象分配空间的任务实际上等同于把一块确定大小的内存块从Java堆(Heap)中划分出来
我们知道堆内存是由GC来管理的,根据GC垃圾收集器的不同,内存划分方式分为以下两种:
-
指针碰撞
Java堆中的内存绝对规整,只需根据对象大小,把指针挪动一段与对象大小相等的距离,分配内存即可
对应的是Serial、ParNew等使用标记——整理算法的垃圾收集器
-
空闲列表
Java堆中的内存并不规整,无法根据偏移量划分内存。虚拟机必须维护一个列表,记录内存的使用情况,将空闲内存分配给对象实例
对应的是CMS这种基于标记——清除算法的收集器,由于此算法会导致内存碎片的产生,所以内存并不规整
3、成员变量赋默认值
内存分配完成之后,虚拟机需要把内存空间都初始化为零值。这步操作保证对象的实例字段在Java代码中可以不赋初值就直接使