读 - 深入理解java虚拟机 - 笔记(七-1) - Java内存区域(2章)-对象创建

本文详细介绍了Java中对象创建的五个步骤:类加载检查、内存分配、对象内存初始化、对象设置及实例初始化方法执行。深入探讨了不同内存分配方式如指针碰撞与空闲列表,以及线程安全问题解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Java的对象几乎都产生于堆中,但是对于对象是怎么产生的,具体在new过程中执行了什么,不能不清楚,至少也应该知道一些知识点。

JVM在new过程中执行了5个步骤去创建一个对象:

1.相应类的加载检查。

2.为对象分配内存。

3.对象内存初始化为零。

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

5.执行对象实例<init>方法进行初始化。


1.相应类的加载检查。

类是否已经加载是需要确定的,我们知道类的加载只执行一次,类加载过程中会对类的静态属性进行初始化。那么JVM在遇到new指令时,先检查指令参数是否能子啊常量池中定位到一个类的符号引用。

1)如果定位到,表名这个类已经被加载,解析,初始化过,可以直接使用了。

2)如果定位不到,就需要先去执行类的加载。

2.为对象分配内存。

对象的内存在类加载完成之后变完全确定了,因此为对象分配内存就是把一块确定大小的内存从Java堆里划分出来。就有必要讨论一下分配方式了。
2.1)分配方式:

指针碰撞:它的前提是Java堆是绝对完整的,一边是用过的内存,一边是空闲的内存,中间存在一个指针作为边界指示器。关于这个指针碰撞,其实比较感兴趣,但  是网上搜了一圈,毛都没有,都是一笔带过~~~~希望知情者能提供相应的介绍文档。

空闲列表:那么如果Java堆不是完整的,用过的和空闲的相互交错,需要维护一个列表,记录哪些内存是可用的。在分配时查表找到一个足够大的内存,并更新列  表。

这边可以看见,Java堆是否完整其实取决于采用了哪种垃圾回收算法,带有标记-整理的算法,可以采用指针碰撞的方式。比如Serial,ParNew,而CMS需要采用空闲列表

2.2)线程安全问题:

看到这边的时候我想到的是单例里会出现对象分配到一半的情况,后续去研读设计模式时可以看下。

并发出现时,上述两种分配方式都不是线程安全的。

同步处理:即CAS理念,对于CAS是啥不做解释,

本地线程分配缓冲区:Thread Local Allcation Buffer(TLAB)。这就将内存分配的动作按照线程划分在不同的空间中进行,当TLAB用完之后分配新的TLAB时做同步 处理。

3.对象内存初始化为零。

这一步和类加载过程中链接里的准备阶段一致,将分配到内存中都初始化为零值(对象头不在其内),如果使用了TLAB方式,这一步可以提前至TLAB分配时进行。这一步确保了对象的实例字段在Java代码中可以不赋初始值就直接使用,程序能访问到这些字段的对应的零值,注意这边还没有进行初始化步骤,可以理解为成员变量的初始化操作。

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

必要的设置过程,类似,对象是哪个类的实例等等。


5.执行对象实例<init>方法进行初始化。

此步骤才会执行对象的初始化操作,就是实例构造器,这个构造器其实不止构造函数这么简单,我所知道的包括实例代码块,实例变量的初始化,最后才是构造函数。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值