当前位置:网站首页>JVM系列之对象的创建
JVM系列之对象的创建
2022-07-04 18:32:00 【a_ittle_pan】
起笔
“学而不厌,诲人不倦”
参考书籍:“深入理解java虚拟机”
对象的创建
案例代码:
public static void main(String[] args) {
Object o = new Object();
}
反编译(javap -c ApplicationContextStarter.class)得到的结果:
public class com.disaster.ApplicationContextStarter {
public com.disaster.ApplicationContextStarter();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: new #2 // class java/lang/Object
3: dup
4: invokespecial #1 // Method java/lang/Object."<init>":()V
7: astore_1
8: return
}
通过案例去解析整个对象的创建过程,分析main方法中的字节码指令(ApplicationContextStarter()是构造器方法,我们这里不去过多关注):
1.当java虚拟机遇到字节码new指令时,首先会去检查这个指令的参数是否能在常量池(方法区)中定位到一个类的符号引用,并且检查这个符号引用代表的类是否已被加载、解析和初始化过。如果没有,那必须先执行相应的类加载过程(前几篇的博客有讲),案例中new关键字会触发Object的初始化过程也就是上图中的invokespecial指令(dup指令:复制操作数堆栈上的顶部值,并将重复的值推送到操作数堆栈上。除非值是类别1计算类型的值,否则不得使用dup指令)。
这里还需要注意一点的是类加载机制中的类初始化时机,这个内容在类加载系列文章中未提及(个人觉得放这里用案例来讲解会比较容易懂),所以在此做一个说明。
jvm规范严格规定有四种情况类是必须要进行初始化的,对于这四种情况原文描述如下:
- 遇到new、getstatic、putstatic或invokestatic这4条字节码指令时,如果类没有进行过初始化,则需要先触发其初始化。生成这4条指令最常见的java代码场景是:使用new关键字实例化对象的时候、读取或设置一个类的静态字段(被final修饰、已在编译期把结果放入常量池的静态字段除外)的时候,以及调用一个类的静态方法的时候。
- 使用java.lang.reflect包的方法对类进行反射调用的时候,如果类没有进行过初始化,则需要先触发其初始化。
- 当初始化一个类的时候,如果发现其父类还没有进行过初始化,则需要先触发其父类的初始化
- 当虚拟机启动时,用户需要指定一个要执行的主类(包含main()方法的那个类),虚拟机会先初始化这个主类
2.类加载通过后,接下来虚拟机将为新生对象分配内存。对象所需内存大小在类加载完成后就可以确定(对象的内存布局,这里的大小确定由jvm完成)
3.对象大小确定完之后开始分配堆内存,jvm为对象分配内存有两种方案,选择那种分配方式由java堆是否规整决定,而java堆是否规整又由所采用的垃圾收集器是否带有压缩整理功能决定的,下面是两种内存分配方案:
指针碰撞
如果内存是规整的,那么虚拟机将采用的是指针碰撞法(Bump The Pointer)来为对象分配内存),意思是所有用过的内存在一边,空闲的内存在另一边,中间放着一个指针作为分界点的指示器,分配内存就仅仅是把指针指向空闲那边挪动一段与对象大小相等的距离罢了。如果垃圾收集器选择的事Serial、ParNew这种基于压缩算法的,虚拟机采用这种分配方式。一般使用带有compact(整理)过程的收集器时,使用指针碰撞)维护一个列表
如果内存不是规整的,已使用的内存和未使用的内存相互交错,那么虚拟机将采用的是空闲列表法来为对象分配内存。意思是虚拟机维护了一个列表,记录哪些内存块是可用的,再分配的时候从列表中找到一块足够大的控件划分给对象实例,并更新列表上的内容。这种分配方式成为“空闲列表(Free List)”
4.在对象分配内存期间还需要考虑一个问题:对象创建在虚拟机中是非常频繁的行为,即使仅仅修改一个指针所指向的位置,在并发的情况下也并不是线程安全的,可能出现正在给对象A分配内存,指针还没来得及修改,对象B又同时使用了原来的指针来分配内存的情况。解决这个问题有两种可选的方案:
- 采用CAS配上失败充实保证更新的原子性
- 每个线程预先分配一块TLAB–通过-XX:+/-UserTLAB参数来设置(在前几篇文章中有提及,到时候可以专门出一期去讲解TLAB)
5.内存分配完成之后,虚拟机必须将分配到的内存空间(不包括对象头)都初始化为零值,如果使用了TLAB的话,这一项工作也可以提前至TLAB分配时顺便进行。这步操作保证了对象的实例在java代码中可以不赋初始值就可以直接使用,使程序能访问到这些字段的数据类型所对应的零值。
6.赋值操作完成之后,虚拟机还要对对象进行必要的设置,将对象的所属类(即类的元数据信息)、对象的HashCode和对象的GC信息、锁信息等数据存储在对象的对象头中。这个过程的具体设置方式取决于JVM实现
7.执行init方法:在上面的几个步骤全部完成之后,从虚拟机的角度的来看,一个新的对象已经产生了。但是从Java程序的视角看来,对象创建才刚刚开始–构造函数(即Class文件中的< init >()方法还没有执行),所有的字段都为默认的零值,对象需要的其他资源和状态信息也还没有按照指定的意图构造好。一般来说,new执行之后会紧接着执行< init >()方法(当使用new关键字去创建对象时后面会紧跟着()方法也就是案例的class图中invokespecial指令)。到此一个真正可用的对象才算被构造出来。
8.构造Object对象完之后通过astore_1指令将对象的内存地址赋值给o变量
以上的内容是从jvm内存的角度去讲解的对象分配,如果从垃圾回收的角度来看的话大致如下图所示(需要我们去区分这两种角度的过程);
边栏推荐
- Lenovo explains in detail the green smart city digital twin platform for the first time to solve the difficulties of urban dual carbon upgrading
- Detailed explanation of issues related to SSL certificate renewal
- Shell 编程核心技术《二》
- Matrix flip (array simulation)
- 升级智能开关,“零火版”、“单火”接线方式差异有多大?
- Reflection (I)
- Summary and sorting of 8 pits of redis distributed lock
- BCG 使用之CBCGPProgressDlgCtrl进度条使用
- The 15th youth informatics competition in Shushan District in 2019
- 测试工程师如何“攻城”(上)
猜你喜欢
MySQL数据库基本操作-DDL | 黑马程序员
Detailed explanation of the binary processing function threshold() of opencv
BCG 使用之CBCGPProgressDlg进度条使用
Pythagorean number law (any three numbers can meet the conditions of Pythagorean theorem)
联想首次详解绿色智城数字孪生平台 破解城市双碳升级难点
Use canal and rocketmq to listen to MySQL binlog logs
PointNeXt:通过改进的模型训练和缩放策略审视PointNet++
西门子HMI下载时提示缺少面板映像解决方案
BCG 使用之新建向导效果
Pointnet/Pointnet++点云数据集处理并训练
随机推荐
有关架构设计的个人思考(本文后续不断修改更新)
Pythagorean number law (any three numbers can meet the conditions of Pythagorean theorem)
ftp、sftp文件传输
Hough Transform 霍夫变换原理
The 15th youth informatics competition in Shushan District in 2019
联想首次详解绿色智城数字孪生平台 破解城市双碳升级难点
2021 合肥市信息学竞赛小学组
Is it safe to open an account at Great Wall Securities? How to open an account when buying stocks
Socket programming demo II
Bi skills - permission axis
长城证券开户安全吗 买股票怎么开户
Technologie de base de la programmation Shell IV
2014 Hefei 31st youth informatics Olympic Games (primary school group) test questions
矩阵翻转(数组模拟)
An example of multi module collaboration based on NCF
生成XML元素
Pytorch学习(四)
Shell 编程核心技术《二》
2021 Hefei informatics competition primary school group
mysql中explain语句查询sql是否走索引,extra中的几种类型整理汇总