对象的创建和分配

本文详细介绍了Java中对象的创建过程,包括类加载、内存申请、成员变量初始化及构造方法调用。同时,讨论了对象的内存布局,包括对象头、ClassPointer、数组长度和实例数据等。此外,探讨了对象定位的句柄池和直接指针两种方式,以及对象在堆内存中的分配策略,如TLAB和Eden区的作用。
摘要由CSDN通过智能技术生成

1. 对象创建过程

创建一个对象,首先是把class文件加载到内存,具体包括三步:具体请看class文件加载过程https://blog.csdn.net/wqc8994/article/details/107928769。然后需要给对象申请内存,接下来成员变量赋默认值,最后调用构造方法。调用构造方法时先调用父类构造方法,然后成员变量赋初始值,接着在执行构造方法语句。

2. 对象的内存布局

对象的内存布局分为两种,一种为普通对象,一种为数组对象。

普通对象数组对象
对象头对象头
ClassPointer指针ClassPointer指针
实例数据数组长度
Padding对齐数组数据
 Padding对齐

对象头:Hotspot被称为markword,长度为8个字节。

ClassPointer指针:指向对应的class对象,开启-XX:+UseCompressedClassPointers为4个字节,不开启为8个字节。

数组长度:4个字节

实例数据/数组数据:1. 基本类型   基本类型数据长度

                                 2. 引用类型   -XX:+UseCompressedOops开启为4字节,不开启为8字节 

Padding对齐:是整个对象长度为8的倍数

3. markword具体内容

锁状态25bit4bit1bit2bit
23bit2bit是否偏向锁锁标志位
无锁态对象的hashcode分代年龄001
轻量级锁指向栈中锁记录的指针00
重量级锁指向互斥量(重量级锁)的指针10
GC标记11
偏向锁线程IDEpoch分代年龄101

4. 对象定位

对象定位有2种方式:句柄池和直接指针。

句柄池:java堆中划分一块内存作为句柄池,句柄包含了对象实例数据的指针和对象类型数据的指针,Java栈本地变量表的ref存储的是句柄地址。

直接指针:堆对象包含对象类型数据的指针和对象实例数据,Java栈本地表量表的ref存储的是对象地址。

HotSpot是使用了直接指针定位对象。

5. 对象分配

对象创建时首先尝试在栈内存分配,如果栈内存分配不下,特别大的对象就直接分配在堆内存老年代,如果不大,首先本地线程分配,本地线程分配不下分配到eden区。当GC年龄到时再转移到老年代。流程如下图:

TLAB:Thread Local Allocation Buffer,线程本地分配缓存区。每个线程在eden区占用1%空间为该线程独有。不与其他线程产生争用。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值