返回
JVM里的对象:创建过程、内存分配与访问分布
见解分享
2023-10-05 09:53:03
对象创建
在JVM中,对象的创建过程大致分为以下几个步骤:
-
类加载检查 :当虚拟机需要执行一条new指令时,首先会去检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并且检查这个符号引用是否已经被加载、解析初始化过。如果没有,那必须先执行相应的类加载过程。
-
分配内存 :在类加载检查通过后,接下来虚拟机将为新生对象分配内存(所谓的内存分配实际上是指为对象计算在堆中的起始地址,并更新该地址在虚拟机内部的数据结构)。这一块内存的分配有两种情况:
- Eden区分配 :如果在Java堆中存在Eden区,那大部分情况下对象都是在这里分配的。不过,这并不是绝对的,当Eden区没有足够空间时,也可以在其他Survivor区分配内存。
- 大对象直接进入老年代 :如果对象的大小超过了Eden区的阈值,或者对象是一组连续的大对象,那通常会直接进入老年代。
-
初始化对象 :当内存分配完成后,对象需要进行初始化。初始化主要分为两步:
- 为对象的每一个字段赋予一个默认值 :Java里对基本类型和引用类型有不同的默认值。对于基本类型,默认值为0、false或null;对于引用类型,默认值为null。
- 执行对象的构造方法 :接着虚拟机会执行对象的构造方法,对对象进行进一步的初始化。
对象的内存布局
在JVM中,对象在内存中的布局大致如下:
-
对象头 :对象头存储了一些关于对象的基本信息,比如对象的哈希码、类型指针、GC标记位等。对象头的具体内容和结构与虚拟机的实现有关。
-
实例数据 :实例数据是指对象中存储的具体数据,比如对象的字段值、继承的父类字段值等。
-
对齐填充 :为了保证对象的内存地址是偶数,虚拟机可能需要在对象头和实例数据的后面添加一些对齐填充字节。
对象的访问分布
在JVM中,对象在内存中的布局与访问方式紧密相关。对象访问主要分为以下几种情况:
- 实例域访问 :实例域访问是指对对象字段的访问。实例域的访问方式与对象的内存布局密切相关。
- 方法调用 :方法调用是指对对象方法的调用。方法调用通常需要通过对象指针来访问对象,然后才能调用对象的方法。
- 数组访问 :数组访问是指对数组元素的访问。数组访问也需要通过对象指针来访问数组,然后才能访问数组元素。
总结
本文深入探讨了JVM中的对象创建、内存布局以及访问分布。从类加载检查和分配内存开始,逐步解析对象创建的过程,并剖析对象的内存结构,包括对象头和实例数据等组成部分。同时,我们将探索对象的访问分布,包括实例域的访问以及方法的调用,分析它们在内存布局中的体现。本文旨在为读者提供JVM对象创建、内存布局和访问分布方面的深入理解,帮助他们编写更加高效、健壮的Java程序。