0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

浅析JVM之对象创建流程及对象内存布局

jf_78858299 来源:北洋洋洋 作者:北洋 2023-02-02 11:16 次阅读

对象创建流程

JAVA虚拟机碰到new字节码指令时,首先会去常量池中查找是否有对应的类名(也就是去查找是否有对应的符号引用),然后去检查这个符号引用代表的类是否已经被加载,解析和初始化过。如果没有会先进行类加载过程。

当类加载后,虚拟机将会为其分配内存,为其分配的内存大小是可知的,下面的内存布局将会讲解为什么是可知的。

分配内存

分配内存这时候有两种情况:

1.假如堆里面的内存是整齐的,用过的在一边,没有用过的内存放在另外一边(后期配图),这个时候中间有个指针来作为两边内存的界限,当内存分配时,指针移动对象内存大小对应的距离即可,这种叫==指针碰撞==。

2.堆里面的内存空间不是规整的,这就需要记录下来哪些内存是可用的,哪些内存是已经被占用了的。这种方式就叫做==空闲列表==:将内存中空闲内存块记录到列表里面。当分配对象时,直接从空闲列表里面进行取出对应大小的内存块即可。

这两种情况又是根据采用的垃圾收集器是否带有==空间压缩整理的能力==划分,如果垃圾收集器已经具备了空间压缩整理的能力那么他的内存空间就是==被整理好的==,直接使用==指针碰撞==就好;但是如果是基于清除算法决定的垃圾回收器时,就只能用复杂的空闲列表来分配内存。

并发解决方法

但是如果发生并发的话,可能在分配一个对象空间的时候又碰到另外一个线程也在分配空间,这个时候就会出现问题,解决方式有两种:

1.通过CAS进行同步处理,基于失败重试的原则;2.将堆里面的空间进行按线程分配,每个线程在队中都会有块内存,当线程分配内存时,直接分配到自己线程的那块内存当中,当那小块内存用完时,在进行CAS同步申请新的内存,这种小块内存叫做==本地线程分配缓存(TLAB)==。

设置初始值

==分配完内存之后需要给这部分内存设置零值,不包括对象头。当通过TLAB分配内存时,其实在分配内存的时候就可以设置零值,不需要等到分配完在设置,因为这部分内存区域是已知的不会出现分配时产生并发的问题==

在程序中可能会出现的问题

解释:这步操作也就是说当对象分配到内存后就可以直接使用里面的字段,==但是这个是初始值==,如果说当我分配完内存后直接使用这个字段的话程序肯定会出问题(因为CPU是乱序执行的,当两个操作互不关联时,一个操作耗时一个操作不耗时,这时候CPU会进行优化让不耗时的先运行。而且一个创建对象的过程需要多行字节码来完成,所以可能会出现重排序的问题,但是这个概率特别低)这时候就需要用volatile关键字来保证有序性。

❝其本身是通过在JVM平台上面的Load,Store两个读写屏障组合来保证的,对应于intel的X86来说是基于MESI协议来保证的。其实JVM平台规定了一些不能乱序执行的原则:HappenBefore原则,里面就规定了volitaile关键字

设置对象头

当对象中的字段设置为对应的默认值(零值)时,需要设置对象头里面的数据,这部分数据包括两部分:

对象头数据结构

1.==对象自身运行时的数据== 比如:哈希码(延迟到真正调用hashcode()方法时才生成) 锁状态标志 线程持有锁 偏向锁的线程ID 偏向时间戳 对象分代年龄 ...... 在未开启压缩指针的情况下,根据32位虚拟机和64位虚拟机不同,这部分数据的总大小分别是32个比特和64个比特。这部分数据叫做“Mark Word”,由于对象运行时存储的数据很多,所以Mark Word是一个动态的数据结构,有些数据其实根本用不到所以某些数据其实是没有必要立马就存储的。

❝32位的虚拟机中,MarkWord是32个比特,其中哈希码占用25个比特,分代年龄占用4个,锁标志位占用两个,剩下的另外一个比特固定为0。

2.==类型指针== 指向类的元数据信息,通过这个指针来确定该对象属于哪个类的实例。

❝(不是所有的虚拟机都必须在对象数据上设置类型指针)

==当对象是数组。。。。==

❝如果对象是数组,在对象头中还会记录数组长度,普通JAVA对象可以通过找到类的元数据信息确定JAVA对象的大小,但是数组长度是不能通过类的元数据信息推导出来的,所以需要在对象头中设置数组长度

Class文件的<.init>

当设置完字段的默认值和对象头的数据后,这个时候该调用Class对象的<.init>方法了即构造函数。

对象的内存布局

当了解完前面的对象创建流程时,相信对于对象在堆中的内存布局也已经有两大概的轮廓了,接下来进行总结:

==分为三部分:对象头,实例数据,对齐填充==

1.对象头前面已经详细讲过了,就不在阐述了

2.实例数据:记录父类和当前类中定义的字段,存储的顺序默认是:long/doubles , ints , shorts/chars , bytes/booleans , oops。默认顺序遵从的原则是相同宽度的字段分配到一起,接着父类定义的变量在子类定义的变量的签名。

3.对齐填充:==不是必然的== 占位符。由于HotSpot虚拟机自动内存管理系统要求对象的起始地址必须是8字节的整数倍,也就是对象的大小都必须是8的倍数。对象头刚刚说了无非是32比特或者64比特默认就是八字节的,所以当实例数据满足八的倍数时,就不需要占位符,这部分数据也就没有;如果不满足八的倍数,将添加占位符使整个对象大小为八的倍数。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • JAVA
    +关注

    关注

    19

    文章

    2904

    浏览量

    102994
  • JVM
    JVM
    +关注

    关注

    0

    文章

    152

    浏览量

    12126
  • 虚拟机
    +关注

    关注

    1

    文章

    855

    浏览量

    27377
收藏 人收藏

    评论

    相关推荐

    请问单例对象会被jvm的gc时回收吗?

    单例对象会被jvm的gc时回收吗?
    发表于 11-09 07:02

    解读rtt的c的面向对象对象创建及其启动初始化流程

    解读rtt的c的面向对象对象创建及其启动初始化流程,最后总结面向对象语言与c面向对象的区别。目
    发表于 07-05 11:01

    java如何创建对象的分析

    作为Java开发者,我们每天创建很多对象,但我们通常使用依赖管理系统,比如Spring去创建对象。然而这里有很多创建
    发表于 09-27 14:36 0次下载

    使用JavaScript创建对象的方法和案例

    Javascript中的一切几乎都是对象,无论是数组还是函数。本文将教你使用JavaScript创建对象的三种方法。
    的头像 发表于 07-06 09:41 2722次阅读

    一文详解Java对象内存布局

    这个实例对象是以怎样的形态存在内存中的? 一个Object对象内存中占用多大? 对象中的属性是如何在
    发表于 09-30 14:38 1073次阅读
    一文详解Java<b class='flag-5'>对象</b>的<b class='flag-5'>内存</b><b class='flag-5'>布局</b>

    JVM内存布局的多方面了解

      JVM内存布局规定了Java在运行过程中内存申请、分配、管理的策略,保证了JVM的稳定高效运行。不同的
    发表于 07-08 15:09 335次阅读

    在JavaScript中动态的创建QML对象

    在实际QML应用开发中,我们可以在JavaScript中动态的创建QML对象。这样做可以延迟对象的实例化,当我们在需要创建对象的时候才在Ja
    的头像 发表于 09-01 10:42 1276次阅读

    探讨JVM内存布局

    JVM内存布局规定了Java在运行过程中内存申请、分配、管理的策略,保证了JVM的稳定高效运行。
    的头像 发表于 09-09 15:57 585次阅读

    JVM入门之对象创建流程内存布局

    当JAVA虚拟机碰到new字节码指令时,首先会去常量池中查找是否有对应的类名(也就是去查找是否有对应的符号引用),然后去检查这个符号引用代表的类是否已经被加载,解析和初始化过。如果没有会先进行类加载过程。
    的头像 发表于 02-10 11:46 302次阅读

    Java中创建对象有哪些方式

    1 问题 作为Java开发者,经常创建很多对象,你是否知道Java中创建对象有哪些方式呢?
    的头像 发表于 02-24 10:29 854次阅读

    JVM内存布局详解

    JVM内存布局规定了Java在运行过程中内存申请、分配、管理的策略,保证了JVM的稳定高效运行。不同的J
    的头像 发表于 04-26 10:10 343次阅读
    <b class='flag-5'>JVM</b><b class='flag-5'>内存</b><b class='flag-5'>布局</b>详解

    Java反射技术实现对象创建

    一. 基础概念 Java中,一般我们创建一个对象可能会选择new一下个实例。但是随着我们技术的不断提升,我们也学习到了,可以通过反射技术实现对象创建。 可是,你有没有想一下,什么时候
    的头像 发表于 05-22 14:25 1603次阅读
    Java反射技术实现<b class='flag-5'>对象</b>的<b class='flag-5'>创建</b>

    详解Java虚拟机的JVM内存布局

    JVM内存布局规定了Java在运行过程中内存申请、分配、管理的策略,保证了JVM的稳定高效运行。不同的J
    的头像 发表于 07-13 09:52 317次阅读
    详解Java虚拟机的<b class='flag-5'>JVM</b><b class='flag-5'>内存</b><b class='flag-5'>布局</b>

    JVM内存对象监控和优化问题描述及解决办法

    服务器内存问题是影响应用程序性能和稳定性的重要因素之一,需要及时排查和优化。本文介绍了某核心服务内存问题排查与解决过程。首先在JVM与大对象优化上进行了有效的实践,其次在故障转移与大
    的头像 发表于 08-28 11:39 626次阅读
    <b class='flag-5'>JVM</b><b class='flag-5'>内存</b>大<b class='flag-5'>对象</b>监控和优化问题描述及解决办法

    jvm内存区域由哪几部分组成

    方法栈。下面将详细介绍这些部分。 堆内存(Heap Memory):堆内存JVM中最大的一块内存区域,用来存储对象实例和数组
    的头像 发表于 12-05 14:10 295次阅读