java中对象的创建
我们知道,Java对象实例是由Java运行时数据区的堆所管理的。我们以HotSpot为例,来探讨关于Java对象的创建,对象的内存布局,对象的访问定位
对象的创建:
1、当java虚拟机遇到new指令时,会通过new指令后的参数到常量池中定位这个类的符号引用,检查这个符号引用代表的类是否被加载,连接,初始化,如果没有,则要先执行相应的类加载过程。
2、在类加载检查通过后,虚拟机就要为新生对象分配内存。内存的分配主要有两种方式:1、指针碰撞,2、空闲列表。
3、内存分配完成之后,Java虚拟机必须将分配到的内存(对象头除外)赋初始值零。这一步保证了对象的实例字段在Java代码中不用赋初始值就可以使用。
4、接下来,Java虚拟机还会对对象进行一系列的设置。如这个对象是哪个类的实例,如何找到类的元数据信息,对象的GC分代年龄等信息。这些信息存放在对象的对象头之中。
5、至此,从虚拟机的角度来看,一个对象的创建已经结束了,但是从Java程序来看,对象的创建刚刚开始——构造函数,即class文件中的<init>()方法还没有执行。一般来说,new指令后面会执行<init>()方法,这样一个真正的对象才被构造出来。
对象的内存布局:
在HotSpot虚拟机中,对象的内存布局分为三部分:对象头,实例数据和对齐填充。
对象头包含两类信息:1、用于存储对象自身的运行时数据,比如哈希码、GC分代年龄、锁状态标志等。2、用于存储类型指针,即对象指向自己类型元数据的指针,Java虚拟机可以通过这个指针确定对象是哪个类的实例。
实例数据则是对象真正存储的有效的信息,即我们在类中所定义的各种类型的字段,无论是父类所继承下来的,还是在子类中所定义的。
对齐填充并不是必须存在的,它起着占位符的作用。
对象的访问定位:
对象的访问定位是通过栈中的reference数据来操作堆上的具体对象。主流的访问方式有两种:使用句柄和直接指针。
句柄访问会在堆上开辟出一块空间来存储实例数据和类型数据的各自地址信息,这块内存空间就是句柄池,而reference存储的就是句柄池的地址信息。
直接指针方式,reference存储的直接就是对象地址。这种方式需要考虑在对象的内存布局中如何放置类型数据的相关信息。
TLAB(Thread Local Allocation Buffer):每个线程在java堆中预先分配一块内存。利用-XX:+/-UseTLAB来启用或禁止使用TLAB
参考:《深入理解java虚拟机》第三版——周志明
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)