java对象的创建与内存分配机制

本文详细探讨了Java中对象的创建过程,包括类加载检查、分配内存(如使用TLAB)、初始化零值、设置对象头等步骤。此外,还讲解了对象在内存中的分配策略,如栈上分配、Eden区分配、大对象直接分配到老年代等。最后,讨论了对象的内存回收机制,如垃圾标记算法和各种引用类型。
摘要由CSDN通过智能技术生成

对象的创建与内存分配机制

对象的创建

java中对象的创建过程如下图所示分为这几步:类加载检查、分配内存、初始化、设置对象头、执行init方法

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bL9W0Ebb-1678459769746)(picture/性能调优/123315)]



类加载检查

检查当前要创建对象所对应的类是否被加载过,类元数据信息是否已经在方法区中保存过,如果没有则会去进行类加载的过程,如果加载了则进行下一步



分配内存

这一部分需要考虑两点:

  • 应该将哪一块内存区域分配给对象
  • 如何解决多个线程并发分配同一块内存问题

如何分配内存

java中有两种为对象分配内存的方式:

  • 指针碰撞(Bump the Pointer) 默认使用

    对于绝对工整的内存区域,一边是已经分配的内存,一边是未分配的内存,中间有一个指针分割。

    经过内加载后就已经知道了此对象会占用多大的内存,从指针位置开始往后分配一块内存给该对象

  • 空闲列表(Free List)

    对于内存比较碎片化,部署绝对工整的情况,就需要使用空闲列表机制来分配内存了,JVM底层会维护一个空闲列表,然后选出一块合适该对象的内存区域进行分配

解决并发分配问题

在多线程的情况下,就可以会出现多个线程都再指针移动前读取到了当前指针的位置,然后把后面的一块内存区域进行了重复分配。解决这个问题有两种方法:

  • CAS算法

    再使用内存前先进行一次验证,比如判断指针是否移动了,如果验证不通过则进行重试

  • TLAB,JDK8默认使用

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

    为每个线程在Eden区中事先分配一块内存区域,各个线程就在自己的这块区域中进行分配,这样就不会有并发问题,当这块内存区域不够使用时在使用CAS算法在Eden去中分配

    通过-XX:+/-UseTLAB参数来设定虚拟机是否使用TLAB(JVM会默认开启-XX:+UseTLAB),-XX:TLABSize 指定TLAB大小。



初始化零值

为对象的属性赋零值,这里需要注意,在类加载的时候是操作的静态变量,而这里才是操作的普通成员变量

初始化零值的作用是:避免了对象属性没有初始化就被使用



设置对象头

对象头的作用是:保存Hash值、分代年龄、锁信息、指向方法区中的类元信息等等

java的对象一般分为三部分:对象头、实例属性、对其填充

  • 对象头接下来详细讲
  • 实例属性:保存此对象各个属性的值
  • 对其填充:保证整个对象占用内存是8字节的整数倍

对象头如下图所示又分为三个部分

  • mark word标记阶段

    记录对象h

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值