JVM系列2:HotSpot虚拟机对象

算法云栖鹤
• 阅读 2057

1.对象创建过程:

 JVM系列2:HotSpot虚拟机对象

①.类加载检查:当java虚拟机遇到一条new指令时,首先会去检查该指令的参数能否在常量池中定位到这个类的符号引用,并且检查这个符号引用代表的类是否已被加载、解析、初始化过,如果没有,则必须先执行相应的类加载过程。

②.分配内存:类加载检查完成后,虚拟机将为新对象分配内存空间,且对象所需内存空间大小在其完成类加载检查后即可确定,该过程其实就是在堆中划分一小部分的确定大小的空间,用于存储对象信息。其中分配方式有以下两种:

 JVM系列2:HotSpot虚拟机对象

内存分配的并发问题:

在创建对象时存在线程安全问题,虚拟机采用两种方式来保证创建对象的线程安全:

CAS锁+失败重试:CAS是乐观锁的一种实现形式,虚拟机采用CAS+失败重试来保证更新操作的原子性。
TLAB:为每一个线程预先在Eden区分配一块儿内存,JVM在给线程中的对象分配内存时,首先在TLAB分配,当对象大于TLAB中的剩余内存或TLAB的内存已用尽时,再采用上述的CAS进行内存分配。
乐观锁:乐观锁就是,每次不加锁而是假设没有冲突而去完成某项操作,如果因为冲突失败就重试,直到成功为止

③.初始化零值:内存分配完毕后,虚拟机将该对象分配得到的内存空间全部设置初始值零(不包含对象头部分),该操作可以保证对象的实例字段在代码中即使不赋予初始值就可以直接使用。程序能访问到这些字段的数据类型所对应的零值。

④.设置对象头:初始化零值完成后,虚拟机将对象的一些必要信息存放在对象头中,这些信息包括:例如这个对象是哪个类的实例、如何才能找到类的元数据信息、对象的哈希吗、对象的 GC 分代年龄等信息。另外,根据虚拟机当前运行状态的不同,如是否启用偏向锁等,对象头会有不同的设置方式。

⑤.执行Init方法:完成上述操作后,java虚拟机即完成了一个对象的创建,但是对于java程序而言,对于该对象的一些定制的内容还未进行,<init>方法中包含了程序员的定制需求和意愿,执行完init方法后,对象完成了初始化,此时才是一个可用对象。

2.对象的内存布局

虚拟机中,对象在内存中的存储包括三个部分:对象头、实例数据和对齐填充。

Hotspot虚拟机的对象头:包括两部分信息,第一部分用于存储对象自身的自身运行时数据(哈希吗、GC分代年龄、锁状态标志等等),另一部分是类型指针,即对象指向它的类元数据的指针,虚拟机通过这个指针来确定这个对象是那个类的实例。想学习更多java知识的朋友可以进群:874811168 一起学习 还有全套的免费资料领取

实例数据部分:是对象真正存储的有效信息,也是在程序中所定义的各种类型的字段内容。

对齐填充部分:不是必然存在的,也没有什么特别的含义,仅仅起占位作用。 因为Hotspot虚拟机的自动内存管理系统要求对象起始地址必须是8字节的整数倍,换句话说就是对象的大小必须是8字节的整数倍。而对象头部分正好是8字节的倍数(1倍或2倍),因此,当对象实例数据部分没有对齐时,就需要通过对齐填充来补全。

3.对象的访问定位

Java程序通过java栈上的 reference 数据来操作堆上的具体对象。对象的访问方式有虚拟机实现而定,目前主流的访问方式有①使用句柄和②直接指针两种:

①.使用句柄:使用句柄访问会在java堆中开辟一片区域作为句柄池,栈中的reference中存储的就是对象的句柄地址,而句柄中则包含了对象实例数据和类型数据的地址信息。

 JVM系列2:HotSpot虚拟机对象

在java栈中的reference中,包含了需要引用的对象的句柄地址,然后通过句柄地址在句柄池中找到指向对象实例数据和对象类型数据的指针,从而实现引用该对象。

在此我向大家推荐一个架构学习交流群。交流学习群号874811168 里面会分享一些资深架构师录制的视频录像:有Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化、分布式架构等这些成为架构师必备的知识体系。还能领取免费的学习资源,目前受益良多

优点:引用中存储的是句柄地址,在对象被移动(垃圾回收时对象移动时很常见的)时,只需要改变句柄中的实例数据指针,而引用中存储的句柄地址无需改变

缺点:因为引用对象通过两次指针定位,速度较直接指针访问慢

②.直接指针:使用直接指针访问时,reference中存储的是对象地址:

 JVM系列2:HotSpot虚拟机对象

优点:节省了一次指针定位的操作,速度较快。

点赞
收藏
评论区
推荐文章
blmius blmius
4年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
Wesley13 Wesley13
4年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
qchen qchen
3年前
Java中6种创建对象的方式
1、使用关键字new创建对象java//无参构造Testtest1newTest();//有参构造Testtest2newTest("小明",18);new对象过程中,底层发生了什么?1.类加载JVM检查先是否已经加载,没有则执行类加载过程2.声明类型引用声明一个Test类型的引用test3.堆内存分配类加载步骤中已确定对象所需
Wesley13 Wesley13
4年前
java虚拟机(三)
普通对象的创建(不包括数组和class对象):当虚拟机遇到new指令时,会在常量池中检查是否包含这个类的符号引用(全限定名),通过这个确定是否经过类加载的过程,如果true,为该对象分配内存,对象大小在类加载过程就已经确定。如果false,需要进行类加载。分配内存1、分配内存的方式:指针碰撞:如果内存
浩浩 浩浩
5年前
JVM--对象创建过程
类创建总结根据new的参数在常量池种寻找一个类的符号引用,如果类没有被加载,则进行类加载、解析、初始化。<cinit
九路 九路
5年前
2 Java对象的创建过程
JAVA中创建对象直接new创建一个对象,对么对象的创建过程是怎样的呢?程序运行过程中有许多的对象被创建出来.那么对象是如何创建的呢?一对象创建的步骤1遇到new指令时,检查这个指令的参数是否能在常量池中找到一个符号引用2如果找到符号引用,就检查这个符号引用是否已经被加载,解析和初始化过3如果没有加载过,则执行类加载过程
Wesley13 Wesley13
4年前
FLV文件格式
1.        FLV文件对齐方式FLV文件以大端对齐方式存放多字节整型。如存放数字无符号16位的数字300(0x012C),那么在FLV文件中存放的顺序是:|0x01|0x2C|。如果是无符号32位数字300(0x0000012C),那么在FLV文件中的存放顺序是:|0x00|0x00|0x00|0x01|0x2C。2.  
Wesley13 Wesley13
4年前
Java对象的创建、内存分配和访问
StudentstudentnewStudent();student.study();(1)对象的创建①检查new指令的参数是否能在常量池中定位到一个类的符号引用,检查符号引用代表的类是否已经加载、解析和初始化  类的加载机制(https://www.oschina.net/action/GoToLink?urlhttps%3
Python进阶者 Python进阶者
2年前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这