JVM——对象的创建与内存布局

一、对象的创建过程

对象,又叫实例,是 OOP 的最常用角色。

如何创建一个对象?一般都是使用 new 关键字搭配对象的构造函数:

// 基类的创建
Object obj = new Object();
// 普通用户对象的创建
User user = new User("Tom", 29);
// 服务类对象的创建
Service svic = new ServiceImpl(user);

上述代码创建了三个对象:obj、user、svic。

这个过程大致可以分为以下几个步骤:

  1. 如果该对象的类还未使用过,需要加载类的信息,并完成连接、初始化等操作。参考《JVM——详解类加载过程
  2. 申请对象,内存成员变量赋 default value,此步骤和类加载过程的 preparation 同理。
  3. 调用构造方法<init> : 成员变量顺序赋初始值,执行构造方法语句
  4. 最后将实例数据的指针返回,存储在位于栈中的引用数据中,即引用赋值。

二、对象的内存布局

2.1 内存布局

在JVM 中,对象的内存布局分为:

  1. 对象头(Header),Mark Word + Class Pointer。
  2. 实例数据(Instance Data),包含父类所有字段信息。
  3. 对齐填充(Padding),任何对象大小都必须是 8 字节的整数倍。

对象头包含两类数据:

  1. Mark Word :它是对象自身的运行时数据,在 Hotspot 虚拟机中,该数据长度是 8 字节(64位操作系统)。包括哈希码、GC分代年龄、锁状态标志、偏向线程ID、偏向时间戳等。
  2. Class Pointer :类型指针,–XX:+UseCompressedClassPointers 压缩类型指针,开启时该数据为 4字节,不开启为 8 字节。

2.2 计算对象的内存大小

Java 语言并不具备类似 C 语言中的 sizeOf 函数,可以直接获取对象的大小。但是,Java 提供了一个 agent 机制,可以通过这个机制来计算 Java 对象的内存大小。

Agent 机制简单的理解就是,一个 class 要加载到内存,JVM 可以提供一个 Agent 代理来截获这些 class 文件,以此来读出整个Object 大小。

三、对象的定位

对象的定位指的是,引用是如何找到具体的实例数据地址的?

目前有两种实现方式:句柄池、直接指针。

两种方式各有优劣,句柄池的方式更安全,而直接指针更快。HotSpot 虚拟机是采用直接指针的方式来实现对象定位的。

3.1 句柄池

在这里插入图片描述

3.2 直接指针

在这里插入图片描述

四、对象的分配过程

首先,new 一个对象的时候,先往栈上分配,如果能分配的下,就直接分配在栈上,然后栈一弹出对象就没了。如果栈上分配不下,特别大的话,直接分配到堆内存老年代。如果不大,首先会进行线程本地分配,如果能分配的下,就直接分配,如果分配不下,找 eden 区。

### 对象内存布局的设计原理 对象在计算机内存中的存储方式其数据结构密切相关。通常情况下,对象内存布局由三部分组成:对象头(Header)、实例数据(Instance Data)以及对齐填充(Padding)。以下是关于这些组成部分的具体描述: #### 1. **对象头** 对象头是每个对象的重要组成部分之一,主要用于存储元信息和运行时所需的数据。根据引用的内容[^2],Mark Word 是对象头的核心部分,其设计采用了非固定的灵活结构以适应不同场景下的需求。例如,在某些状态下它可以用来存储锁标志位、哈希码或者GC分代年龄等。 对于数组类型的对象而言,除了上述通用字段外,还需要额外增加一块区域来保存数组长度的信息[^5]。 #### 2. **实例数据** 这是实际存储类属性的地方。按照面向对象编程的原则,当创建一个新的对象时,所有的非静态成员变量都会被初始化并分配相应的空间大小。值得注意的是,即使子类继承自父类,它们各自的字段也会按顺序紧挨着排列在一起形成连续的一段地址区间[^4]。 为了提高缓存命中率减少访问延迟时间,JVM会对各字段重新排序使得相近类型放得更近一些——这就是所谓的“字段重排”。 #### 3. **对齐填充** 由于硬件架构的原因,大多数现代处理器偏好于处理边界对其良好的数据项;因此即便某个特定平台可能允许未对准读写操作也不会抛异常错误,但从性能角度考虑还是应该遵循8字节倍数原则进行适当扩展填补空白区段直至满足条件为止[^3]。 ```java public class Example { private int a; // 占用4字节 private long b; // 占用8字节 } // 假设此例子是在32/64位标准平台上编译运行,则最终占用总空间为16字节(含必要padding) ``` 通过以上分析可以看出,合理规划好内部构成有助于优化整体表现效果同时兼顾资源利用率最大化目标达成情况如何取决于具体实现细节差异程度高低不一而已!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值