JVM:Java对象的创建 &内存布局

116 阅读3分钟

theme: condensed-night-purple

1.对象的创建

前言:Java对象创建过程:限于普通对象,不包含数组和Class对象(JVM生成的Class对象)

流程图

未命名文件.png

1.类加载检查

检查该new指令的参数 是否能在 常量池中 定位到一个类的符号引用
检查 该类的符号引用 代表的类是否被加载过

2.分配内存

对象在类加载完成后,具体的大小就能确定出来, 此时需要在java堆里面划分内存

划分内存方式根据“Java堆内存是否绝对规整”为依据分为两种方式

1.指针碰撞(规整)

 分配形式:在已使用内存中间放一个分界点的指示器 ;分配对象内存 = 把指针向未使用内存 移动一段 与对象大小相等的距离

2.空闲列表(不规整)

分配形式:虚拟机维护着一个 记录可用内存块 的列表,在分配时从列表中找到一块足够大的空间划分给对象实例,并更新列表上的记录

Java堆内存是否绝对规整概念:如果已使用内存和未使用内存分别在两边,没有交错,这就是绝对规整。

Java堆内存是否绝对规整是由“垃圾收集器是否带有压缩整理功能(Compact)决定”:因此Serial,ParNew采用指针碰撞。CMS采用空闲列表

注意:分配内存线程不安全问题;

例如:当前正在给A分配对象,指针还没来的及修改,B已经在拿原来的指针位置来分配内存了

解决方案:

 同步处理分配内存空间的行为(CAS+失败重试的方式,保证更新操作的原子性,cpu消耗大)
 把内存分配根据线程划分,在各自的线程中进行分配。即每个线程先在Java堆里面预先分配一小块内存,如果分配完了,则重新再分配内存,此时需要**同步锁**
 

3.将内存空间初始化为零值

内存分配完成后,虚拟机需要将分配到的内存空间初始化为零(不包括对象头)

4.对对象进行必要的设置

设置 这个对象 是哪个类的 实例,如何才能找到类的元数据信息,对象的HashCode,对象的GC分代年龄

对象的内存布局

  • 问题:在 Java 对象创建后,到底是如何被存储在Java内存里的呢?

  • 答:在Java虚拟机(HotSpot)中,对象在 Java 内存中的 存储布局 可分为三块:

1.对象头 存储区域

 对象自身的运行时数据(如HashCode),GC分代年龄,锁状态标志,线程持有的锁
 对象类型指针(对象指向它的类元数据指针,虚拟机通过这个对象来确定是哪个类的实例)
 注意:如果是数组。对象头还有一块比心记录数组长度的数据
 

2.实例数据 存储区域

代码中定义的字段内容

3.填充 存储区域

占位符(因为大小必须是8字节的整数倍,对象头刚好是8字节的倍数。当实例的数据带下不是8字节的整数倍时候,则就用它来填充至8的倍数)