从JVM分析对象创建的过程

从JVM分析对象创建的过程

如图:

1.类加载检查

虚拟机遇到一条new指令时,首先去检查这个指令的参数是否能在称量翅中定位到一个类的符号引用,并且检查这个符号引用代表的类是否已经被加载、解析和初始化过。如果没有,先对这个类进行加载,然后进行下一步。

Java常见创建对象的方式:

1、new对象

2、clone对象

3、序列化创建对象

4、反射创建对象

5、单例singleton new Instance

2.分配内存

类加载完成后,虚拟机将为新生对象分配内存。对象需要内存的大小在类加载完成之后就可以完全确定,为对象分配空间的任务等同于加你个一块确定大小的内存从Java堆中划分出来。

这个步骤中有两个关键点

1、如何划分内存

划分内存的方式有两种

(1)一种是指针碰撞Bump the Pointer(JVM默认采用这种方式),如果Java堆中的内存是规整的,即使用过的内存在一边,未使用的在另一边,中间放着一个指针作为分界点的指示器,那么内存分配就是指针的移动;

(2)另外一种方式是空闲列表Free LIst,使用的场景比如说采用标记清除的GC算法会产生大量的内存碎片。这个时候无法使用指针碰撞的方式,这时虚拟机会维护一个列表,记录哪些内存是可用的,在分配的时候再列表中找出一块足够大的空间分配给对象实例,并更新列表上的记录。

2、在并发情况下,对象之间可能存在内存竞争,出现指针抢占的问题。

解决并发问题的方法:

(1)CAS(compare and swap) 通俗理解:大家去抢同一个内存,没抢到的继续重试下一块内存空间

虚拟机采用CAS配上失败重试的方式保证更新操作的原子性来对分配内存空间的动作进行同步处理。

(2)本地线程分配缓冲(Thread Local Allocation Buffer,TLAB)

每个线程在Java堆中预先分配一小块内存。通过-XX:+/-UseTLAB参数来设定虚拟机是否使用TLAB(JVM会默认开启-XX:+UseTLAB),-XX:TLABSize 指定TLAB大小。

3.初始化零值

内存分配完成后,虚拟机需要将分配到的内存空间都初始化为零值(不包括对象头), 如果使用TLAB,这一工作过程也可以提前至TLAB分配时进行。

作用:保证了对象的实例字段在Java代码中可以不赋初值就可以直接使用,程序能访问这些字段的数据类型所对应的零值。

4.设置对象头

初始化零值之后,虚拟机要对对象进行必要的设置,例如这个对象是哪个类的实例、如何才能找到类的元数据信息、对象的哈希码、对象的GC分代年龄等信息。这些信息存放在对象的对象头Object Header之中。

对象头在hotspot的C++源码markOop.hpp文件里的注释如下:

cpp 复制代码
// Bit-format of an object header (most significant first, big endian layout below):
//
//  32 bits:
//  --------
//             hash:25 ------------>| age:4    biased_lock:1 lock:2 (normal object)
//             JavaThread*:23 epoch:2 age:4    biased_lock:1 lock:2 (biased object)
//             size:32 ------------------------------------------>| (CMS free block)
//             PromotedObject*:29 ---------->| promo_bits:3 ----->| (CMS promoted object)
//
//  64 bits:
//  --------
//  unused:25 hash:31 -->| unused:1   age:4    biased_lock:1 lock:2 (normal object)
//  JavaThread*:54 epoch:2 unused:1   age:4    biased_lock:1 lock:2 (biased object)
//  PromotedObject*:61 --------------------->| promo_bits:3 ----->| (CMS promoted object)
//  size:64 ----------------------------------------------------->| (CMS free block)
//
//  unused:25 hash:31 -->| cms_free:1 age:4    biased_lock:1 lock:2 (COOPs && normal object)
//  JavaThread*:54 epoch:2 cms_free:1 age:4    biased_lock:1 lock:2 (COOPs && biased object)
//  narrowOop:32 unused:24 cms_free:1 unused:4 promo_bits:3 ----->| (COOPs && CMS promoted object)
//  unused:21 size:35 -->| cms_free:1 unused:7 ------------------>| (COOPs && CMS free block)

5.执行方法

对象按照程序中的设置值进行初始化,区别于第步的初始化零值,这个操作流程是把实际的值赋值给对象。

相关推荐
longlongqin23 分钟前
JVM 内存结构?
jvm
Joeysoda9 小时前
Java数据结构 时间复杂度和空间复杂度
java·开发语言·jvm·数据结构·学习·算法
18你磊哥10 小时前
java重点学习-JVM组成
java·开发语言·jvm
蜜桃小阿雯12 小时前
JAVA开源项目 校园美食分享平台 计算机毕业设计
java·jvm·spring boot·spring cloud·intellij-idea·美食
longlongqin12 小时前
JIT(即时编译)技术
jvm
ZachOn1y18 小时前
Java 入门指南:JVM(Java虚拟机)—— 双亲委派模型(Parent Delegation Model)
java·jvm·后端·java-ee·团队开发·个人开发
寻求出路的程序媛20 小时前
JVM —— 类加载器的分类,双亲委派机制
java·jvm·面试
深鱼~20 小时前
【JVM】垃圾回收机制|死亡对象的判断算法|垃圾回收算法
jvm
Lill_bin20 小时前
JVM内部结构解析
jvm·后端·spring cloud·微服务·云原生·ribbon
视觉小鸟20 小时前
【JVM安装MinIO】
前端·jvm·chrome