2.3 HotSpot虚拟机对象的探秘
以常用的HotSpot虚拟机和常用的内存区域Java堆为例,探讨虚拟机在Java堆中的对象分配,布局和访问的全过程:
对象的创建,对象的内存布局,对象的访问定位。
1.对象的创建
1-文中讨论的对象,仅限于普通Java对象,不包括数组和Class对象
2-对象的创建过程:
1)虚拟机遇到一条new指令时
-判断常量池是否能定位到一个类的符号引用
-如果存在,则检查这个符号引用代表的类是否被加载,解析和初始化
-如果没有被加载,则执行类加载过程
2)类加载检查通过之后,接下来虚拟机就为新生对象分配内存。
-对象所需的内存大小在类加载完成之后是确定的,为对象分配空间等同把一块大小确定的内存空间从Java堆中划分出来。
-指针碰撞
1)假设Java堆内存是绝对规整的,所用过的内存都在放一边,空闲内存放在另一边,中间放着一个指针作为分界点的指示器。
2)那所分配的内存仅仅是把指针向空闲空间那边挪动一段与对象大小相等的距离,这种分配方式称为“指针碰撞”。
-空闲列表
1)如果Java堆的内存不是规整的,已使用的内存和空闲内存相互交错,虚拟机就必须维护一个列表,记录上哪些内存块是可用的。
2)在分配内存的时候,从列表中找到一块足够大的空间分配给对象实例,并更新列表上的记录,这种分配方式称为“空闲列表”。
-选择哪种分配方式由Java堆是否规整决定,而Java堆是否规整又由所采用的垃圾收集器是否带有压缩整理功能决定。
3-除了如何划分可用空间之外,还有一个需要考虑的问题是对象的创建在虚拟机中是非常频繁的,在并发条件下并不是线程安全的。
解决方法有两种:
1)一种是对分配内存动作做同步处理
-实际上虚拟机使用CAS配上失败重试保证更新操作的原子性
2)另一种是把内存分配动作按照线程划分在不同的空间之中进行
-即每个线程在Java堆中划分一小块内存,称为本地线程分配缓冲(TLAB),哪个线程要分配内存,就在哪个TLAB上分配,只有TLAB使用完并分配新的TLAB时,才需要同步操作。虚拟机是否使用TLAB,可以通过参数来设定
4-内存分配完成后,虚拟机要将分配到的内存空间都初始化为零值(不包括对象头),这一步操作保证了对象的实例字段在Java代码中不需要赋初始值就可以直接使用,程序能访问到这些字段的数据类型所对应的零值
5-接下来,虚拟机要对对象头进行必要的设置,例如这个对象是哪个类的实例,如何才能找到类的元数据信息,对象的哈希码,对象的GC分代年龄等信息
6-在上面的工作完成之后,从虚拟机视角上看,一个新的对象已经产生了;但是从Java程序的视角上看,对象才刚刚创建,<init>方法还没执行,所有字段都还为零。
一般来说,执行new指令之后会接着执行<init>方法,把对象按照程序员的意向进行初始化。
2.对象的内存布局
1-在HotSpot虚拟机中,对象的内存布局可分为3块区域:对象头,实例数据,对齐填充
1)对象头
HotSpot虚拟机对象头包括两部分信息:
-第一部分用于存储对象自身的运行时数据
-第二部分是类型指针,即对象指向它的类元数据的指针
-虚拟机通过这个指针确定这个对象是哪个类的实例
-如果对象是一个Java数组,那在对象头还必须有一块用于记录数组长度的数据,因为虚拟机可以通过普通Java对象的元数据信息来确定对象的大小,而无法从数组的元数据中确定数组的大小
2)实例数据
真正存储对象的有效信息
3)对齐填充
占位符的作用。由于HotSpot VM 要求对象的起始地址必须是8字节的倍数,也就是对象的大小必须是8字节的倍数,对象头正好是8字节的倍数,因此,当实例数据不足8字节倍数时,就需要通过对齐填充来补齐。
3.对象的访问定位
1-Java程序通过栈上的reference数据来操作堆上的具体对象。
2-由于reference类型虚拟机规范中只规定了一个指向对象的引用,所以对象的访问取决于虚拟机的实现
3-目前主流的访问方式有:使用句柄和直接指针两种。
1)句柄
-如果使用句柄访问的话,Java堆中将会划分出一块内存作为句柄池,reference中存储的就是对象的句柄地址;
-句柄池包含了对象的实例数据和类型数据各自的地址信息。
2)直接指针
-如果使用直接指针访问,那么Java堆对象的布局就必须要考虑如何放置访问类型数据的相关信息,而reference中存储的直接就是对象的地址
4-这两种访问方式的区别:
1)使用句柄访问最大的好处是reference存储的是稳定的句柄地址,在对象被移动时(垃圾收集时),只会改变句柄中的实例数据指针,而reference本身不需要修改。
2)使用直接指针最大的好处就是访问速度更快,它节省了一次指针定位的时间开销。
5-Sun HotSpot虚拟机使用直接指针方式来进行对象的访问
相关推荐
《HotSpot虚拟机对象探秘》是一份详细探讨Java虚拟机内部对象创建、内存布局以及访问定位的资源。这份资料采用Xmind脑图的形式,旨在帮助读者深入理解JVM的底层原理,尤其聚焦于HotSpot虚拟机。内容涵盖对象实例化、...
复制收集器通过复制活对象到另一段内存区域来实现垃圾收集。 ##### 5. 性能指标 - **吞吐量**:衡量应用程序运行的有效时间占比。 - **垃圾收集开销**:包括垃圾收集过程中的暂停时间以及CPU资源的消耗。 - **暂停...
HotSpot 虚拟机采用了 Generational Garbage Collection(分代垃圾回收)机制,即将 Java 对象分为年轻代、老年代和永久代三个部分。年轻代存储着刚刚创建的对象,老年代存储着长期存活的对象,而永久代则存储着类、...
HotSpot 虚拟机对象探秘是指 HotSpot 虚拟机如何创建和管理 Java 对象。HotSpot 虚拟机对象探秘可以分为以下几个步骤: #### 11.1 对象的创建 对象的创建是 HotSpot 虚拟机对象探秘的第一步,负责创建 Java 对象。...
学习JDK 源码必备,提起HotSpot VM,相信所有Java程序员都知道,它是Sun JDK和OpenJDK中所带的虚拟机,也是目前使用范围最广的Java虚拟机。 但不一定所有人都知道的是,这个目前看起来“血统纯正”的虚拟机在最初...
3. **内存模型(Memory Model)**:HotSpot虚拟机实现了Java内存模型,确保多线程环境下数据的一致性和可见性。 4. **类加载机制(Class Loading)**:HotSpot虚拟机负责加载、验证、准备、解析和初始化类。这部分...
《深入解析JDK7:基于C++的底层源码与HotSpot虚拟机剖析》 在IT领域,Java作为一门广泛使用的编程语言,其性能优化和内部机制一直是开发者关注的焦点。JDK7作为Java发展历程中的一个重要版本,引入了许多创新特性,...
Java 14 Hotspot 虚拟机的垃圾回收调优是提升应用程序性能的关键环节。本指南主要涵盖了垃圾收集器的优化目标、策略以及各种实现,旨在帮助开发者更好地理解如何调整 JVM 参数以满足特定的需求。 优化目标与策略...
Java HotSpot虚拟机是Oracle公司开发的一款高性能的Java虚拟机,它是Java运行环境的重要组成部分,负责解释和优化Java代码,确保程序的高效运行。本文将深入探讨Java HotSpot虚拟机的部分参数及其作用,帮助开发者更...
Java虚拟机(JVM)在创建和管理对象时涉及多个关键概念和技术,这些概念与对象的内存布局、对象头、对象锁以及`synchronized`关键字的底层实现密切相关。在JVM中,对象的创建过程分为几个步骤: 1. **类加载检查**:...
- Java堆是所有线程共享的一块内存区域,主要用来存放对象实例。 - 包括了所有的对象实例和数组。 - 垃圾收集器的主要管理区域,负责清理不再使用的对象。 - 物理上可以是不连续的内存空间,但在逻辑上被视为...
【标题】: "08-java11-hotspot-guide.pdf" 【描述】: 描述表明这份文档是关于Java 11平台中HotSpot虚拟机官方实现的指南。HotSpot是Oracle JDK和OpenJDK中Java虚拟机(JVM)的一种实现,其特点是高性能、跨平台,...
Java应用程序的内存使用是HotSpot虚拟机垃圾回收调整的重要方面。开发人员需要了解Java应用程序的内存使用模式,以便更好地优化垃圾回收性能。Java应用程序的内存使用可以分为栈内存、堆内存和元数据内存三部分。栈...
#### 二、Java虚拟机的组成与功能 JVM主要由以下几个部分组成: 1. **类装载器(Class Loader)**:负责读取并加载Java类文件到JVM中。 2. **字节码校验器(Bytecode Verifier)**:确保加载到JVM中的字节码是安全的,...
对象的创建加载:先去检测new指令能否再常量池中定位到一个类的符号引用,如果未被加载、解析、初始化过 执行相应的类加载过程分配内存: 为对象分配空间时采用指针碰
《深入解析JDK9:C++底层源码与HotSpot虚拟机》 JDK9作为Java发展历程中的一个重要版本,引入了多项创新性改进,其中包括对HotSpot虚拟机的优化和增强。HotSpot虚拟机是Oracle JDK的核心部分,负责运行Java应用程序...
Java虚拟机(JVM)是Java程序的核心组成部分,它负责解析和执行字节码,同时管理内存区域。本文主要探讨虚拟机的历史、运行时数据区域以及内存区域的配置。 首先,虚拟机的历史简述,虽然这里并不需要深入,但我们...
【标题】"jdk-8.0.302.8-hotspot" 是Oracle公司发布的Java Development Kit(JDK)的一个版本,它包含了Java运行时环境(JRE)和用于开发Java应用程序的工具。这个特定的版本是8u302,意味着它是Java 8的更新302版,...
包含参数如下: 1. 内存管理参数 2. 及时编译参数 3. 类型加载参数 4. 多线程相关参数‘ 5. 性能参数 6. 调试参数