浅析JVM对象的创建过程、内存布局以及访问定位
一、对象的创建过程
关于对象的创建,第一反应是 new 关键字。Student stu =new Student("**","18");
就拿这句代码来说:
1、虚拟机首先会去检查Student这个类有没有被加载,如果没有,首先去加载这个类到方法区。
2、然后根据加载的Class类对象创建stu实例对象。
3、需要注意的是,stu对象所需的内存大小在 Student类加载完成后便可完全确定。
4、内存分配完成后,虚拟机需要将分配到的内存空间的实例数据部分初始化为零值,这也就是为什么我们在编写Java代码时创建一个变量不需要初始化。
5、紧接着,虚拟机会对对象的对象头进行必要的设置,如这个对象属于哪个类,如何找到类的元数据(Class对象)、对象的锁信息、GC分代年龄等。
6、设置完对象头信息后,调用类的构造函数。
其实讲实话,虚拟机创建对象的过程远不止这么简单,我这里只是把大致的脉络讲解了一下,方便大家理解。
二、对象的内存布局
刚刚提到的实例数据,对象头,有些小伙伴也许有点陌生,这一小节就详细讲解一下对象的内存布局。
对象创建完成后大致可以分为以下几个部分:
1、对象头:对象头中包含了对象运行时一些必要的信息,如GC分代信息,锁信息,哈希码,指向Class类元信息的指针等。
其中对开发者比较有用的是锁信息与指向Class对象的指针
关于指向Class对象的指针其实很好理解。比如上面那个Student的例子,当我们拿到stu对象时,调用Class stuClass=stu.getClass(); 的时候,其实就是根据这个指针去拿到了stu对象所属的Student类在方法区存放的Class类对象。
2、实例数据:实例数据部分是对象真正存储的有效信息,就是程序代码中所定义的各种类型的字段内容。
3、对齐填充:虚拟机规范要求对象大小必须是8字节的整数倍。
对齐填充其实就是来补全对象大小的。
三、对象的访问定位
谈到对象的访问,还拿上面学生的例子来说,当我们拿到stu对象时,直接调用stu.getName();时,其实就完成了对对象的访问。
但这里要说一下的是,stu虽然通常被认为是一个对象,其实准确来说是不准确的,stu只是一个变量,变量里存储的是指向对象的指针,(如果干过C或者C++的小伙伴应该比较清楚指针这个概念),当我们调用stu.getName()时,虚拟机会根据指针找到堆里面的对象然后拿到实例数据name。
需要注意的是,当我们调用stu.getClass()时,虚拟机会首先根据stu指针定位到堆里面的对象,然后根据对象头里面存储的指向Class类元信息的指针再次到方法区拿到Class对象,进行了两次指针寻找。具体讲解图如下:
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
2020-09-14 mybatis使用记录:#{}与${}区别、缓存机制、传递数组参数和List参数时if-test判空和判断长度的写法、Mybatis查询数据返回基本类型数组
2020-09-14 服务对外提供接口以供不同站点之间使用:Spring Cloud Feign使用记录及携带token请求