JVM运行时数据区--纵向补充--对象的实例化内存布局与访问定位
对象的实例化
创建对象的方式
1.new:最常见的方式(本质是构造器)
变形1 : Xxx的静态方法
变形2 : XxBuilder/XxoxFactory的静态方法
2.Class的newInstance():反射的方式,只能调用空参的构造器,权限必须是public
3.Constructor的newInstance(Xxx):反射的方式,位于java.lang.reflect.Constructor<T> 可以调用空参、带参的构造器,权限没有要求
4.使用clone() :不调用任何构造器,当前类需要实现Cloneable接口,实现clone()
5.使用反序列化:从文件中、从网络中获取一个对象的二进制流
6.第三方库Objenesis
创建对象的步骤
1.判断对象对应的类是否加载、链接、初始化
虚拟机遇到一条new指令,首先去检查这个指令的参数能否在Metaspace的常量池中定位到一个类的符号引用,并且检查这个符号引用代表的类是否已经被加载、解析和初始化。( 即判断类元信息是否存在)。
如果没有,那么在双亲委派模式下,使用当前类加载器以ClassLoader+包名+类名为Key进行查找对应的.class文件。如果没有找到文件,则抛出ClassNotFoundException异常,如果找到,则进行类加载,并生成对应的Class类对象
2.为对象分配内存
首先计算对象占用空间大小,接着在堆中划分一块内存给新对象。 如果实例成员变量是引用变量,仅分配引用变量空间即可,即4个字节大小。
- 如果内存规整,使用指针碰撞
如果内存是规整的,那么虚拟机将采用的是指针碰撞法(BumpThePointer)来为对象分配内存。意思是所有用过的内存在一边,空闲的内存在另外一边,中间放着一个指针作为分界点的指示器,分配内存就仅仅是把指针向空闲那边挪动一段与对象大小相等的距离罢了。如果垃圾收集器选择的是Serial、ParNew这种基于压缩算法的,虚拟机采用这种分配方式。所以一般使用带有compact (整理)过程的收集器时,使用指针碰撞。 - 如果内存不规整,虚拟机需要维护一个列表,使用空闲列表分配
如果内存不是规整的,已使用的内存和未使用的内存相互交错,那么虛拟机将采用的是空闲列表法来为对象分配内存。意思是虚拟机维护了一个列表,记录上哪些内存块是可用的,再分配的时候从列表中找到一块足够大的空间划分给对象实例,并更新列表上的内容。这种分配方式成为“空闲列表(Free List) ”。
说明:选择哪种分配方式由Java堆是否规整决定,而Java堆是否规整又由所采用的垃圾收集器是否带有压缩整理功能决定。
3.处理并发安全问题
在分配内存空间时,另外一个问题是及时保证new对象时候的线程安全性:创建对象是非常频繁的操作,虚拟机需要解决并发问题。虚拟机采用 了两种方式解决并发问题:
- CAS ( Compare And Swap )失败重试、区域加锁:保证指针更新操作的原子性;
- TLAB把内存分配的动作按照线程划分在不同的空间之中进行,即每个线程在Java堆中预先分配一小块内存,称为本地线程分配缓冲区,(TLAB ,Thread Local Allocation Buffer) 虚拟机是否使用TLAB,可以通过一XX:+/一UseTLAB参数来 设定。
4.初始化分配到的空间
Java给对象的属性赋值的操作有如下四种:
① 属性的默认初始化
② 显式初始化
③ 代码块中初始化
④ 构造器中初始化
这里提到的是第①种:初始化分配到的空间指的是①:所有属性设置默认值,保证对象实例字段在不赋值时可以直接使用。
内存分配结束,虚拟机将分配到的内存空间都初始化为零值(不包括对象头)。这一步保证了对象的实例字段在Java代码中可以不用赋初始值就可以直接使用,程序能访问到这些字段的数据类型所对应的零值。
5.设置对象的对象头
将对象的所属类(即类的元数据信息)、对象的HashCode和对象的GC信息、锁信息等数据存储在对象的对象头中。这个过程的具体设置方式取决于JVM实现。
6.执行init方法进行初始化

对象的内存布局
对象头(Header)
包含两部分
- 运行时元数据
- 哈希值( HashCode )
- GC分代年龄
- 锁状态标志
- 线程持有的锁
- 偏向线程ID
- 偏向时间戳
- 类型指针:指向类元数据的InstanceKlass,确定该对象所属的类型
说明:如果是数组,还需记录数组的长度
实例数据(Instance Data)
说明:它是对象真正存储的有效信息,包括程序代码中定义的各种类型的字段(包括从父类继承下来的和本身拥有的字段) 规则:
- 相同宽度的字段总被分配在一起
- 父类中定义的变量会出现在子类之前
- 如果CompactFields参数为true(默认为true),子类的窄变量可能插入到父类变量的空隙
对齐填充(Padding)
不是必须的,也没特别含义,仅仅起到占位符作用
图示小结
示例代码:
public class CustomerTest {
public static void main(String[] args) {
Customer cust = new Customer();
}
}
对象的访问定位
访问对象实例的主要方式有两种:句柄访问、直接指针(HotSpot采用)
句柄访问方式
句柄定位方式优缺点:
缺点:占用空间、间接指向对象实例。
优点:定位稳定:当对象实例发生移动(垃圾回收算法,内存整理算法),则不需要修改reference到句柄的定位地址,仅需要在句柄内修改间接地址,重新定位到对象实例即可。
直接指针方式
hotspot虚拟机采用的是直接指针方式。
JVM运行时数据区--纵向补充--对象的实例化内存布局与访问定位的更多相关文章
- JVM 专题十二:运行时数据区(七)对象的实例化内存布局与访问定位
1. 对象的实例化 1.1 创建对象的方式 new 最常见的方式 变形1 : Xxx的静态方法 变形2 : XxBuilder/XxoxFactory的静态方法 Class的newInstance() ...
- JVM运行时数据区及对象在内存中初始化的过程
JVM运行时数据区 Java虚拟机所管理的内存区域,也称为运行时数据区,分为以下几个运行时数据区,如图所示 程序计数器:当前程序所执行字节码的行号指示器 程序计数器(Program Counter R ...
- Jvm运行时数据区
一:运行时数据区 Java虚拟机在执行Java程序的过程中会把它管理的内存分为若干个不同的数据区域.这些区域有着各自的用途,一级创建和销毁的时间,有的区域随着虚拟机进程的启动而存在,有些区域则依赖用户 ...
- Java内存管理:Java内存区域 JVM运行时数据区
转自:https://blog.csdn.net/tjiyu/article/details/53915869 下面我们详细了解Java内存区域:先说明JVM规范定义的JVM运行时分配的数据区有哪些, ...
- JVM 运行时数据区 (三)
JVM运行时数据区 运行时数据区由 程序计数器.java虚拟机栈.本地方法栈.堆.方法区 组成: 1.程序计数器 每一个Java线程都有一个程序计数器,用于保存程序执行到当前方法的哪一个指令,它是线程 ...
- JVM总结(一):概述--JVM运行时数据区
大三下,趁着寒假重温一遍JVM,准备在一个系列来总价一下学习JVM的整个过程.争取在接下来的一个星期内更新完这一个系列,然后回家过年. JVM运行时数据区 线程私有的数据区 程序计数器 虚拟机栈 本地 ...
- JVM运行时数据区与JVM堆内存模型小结
前提 JVM运行时数据区和JVM内存模型是两回事,JVM内存模型指的是JVM堆内存模型. 那JVM运行时数据区又是什么? 它包括:程序计数器.虚拟机栈.本地方法栈.方法区.堆. 来看看它们都是干嘛的 ...
- JVM运行时数据区和垃圾回收机制
最近参考各种资料,尤其是<深入理解Java虚拟机 JVM高级特性和最佳实践>,大牛之作.把最近学习的Java虚拟机组成和垃圾回收机制总结一下. 你不会的都是新知识,学无止境,每天进步一点点 ...
- Java中的字符串常量池和JVM运行时数据区的相关概念
什么是字符串常量池 JVM为了减少字符串对象的重复创建,其维护了一个特殊的内存,这段内存被成为字符串常量池或者字符串字面量池 工作原理 当代码中出现字面量形式创建字符串对象时,JVM首先会对这个字面量 ...
随机推荐
- Android 禁止ViewPager左右滑动的功能实现
来来来,各位看官~ Look here!!! Android 禁止ViewPager左右滑动的功能实现!! I think it`s so easy,无需重写ViewPager!!! JUST ...
- C# WebAPI项目,不支持HttpPut请求!!!
有点标题党了,这个异常的现象是这样的: 我有一个正在跑的项目,要对接第三方厂家的设备. 对方给的接口文档,里面有一个接口是需要我这边实现的,要求必须是PUT请求方式. 所以我在项目基础上,新增一个W ...
- Jmeter 常用函数(22)- 详解 __intSum
如果你想查看更多 Jmeter 常用函数可以在这篇文章找找哦 https://www.cnblogs.com/poloyy/p/13291704.htm 作用 计算两个或多个整数值的和 语法格式 ${ ...
- HMM隐马尔可夫模型来龙去脉(一)
目录 隐马尔可夫模型HMM学习导航 一.认识贝叶斯网络 1.概念原理介绍 2.举例解析 二.马尔可夫模型 1.概念原理介绍 2.举例解析 三.隐马尔可夫模型 1.概念原理介绍 2.举例解析 四.隐马尔 ...
- Pytools1.0.0发布啦!
大家赶紧来看看,特别好用的. 文档: This is pytools modulethe module is use MIT license MIT License Copyright (c) 202 ...
- 记一次 gltf 模型的绘制性能提升:从ppt到dove,丝滑感受
转换思路 同样一个模型,分别取如下转换思路: 原始模型fbxgltf 原始模型objgltf 但是我在打开中间格式fbx和obj时,发现这两者虽然顶点数量一致,三角形数量一致,但是使用 Windows ...
- ceph 快照,克隆
转载 https://my.oschina.net/wangzilong/blog/1595081 ceph 快照,克隆 ceph是一个非常好的后端存储系统.其中包括最常用的块存储,对象存储,文件系统 ...
- 操作系统-文件系统(5)Linux文件系统管理
主流分区机制有MBR和GPT两种 MBR分区:第一个扇区最重要,里面有:引导代码(Bootstrap code area)及分区表(partition table), 其中Bootstrap code ...
- All in One 你想知道的 hacker 技术都在这里
作者:HelloGitHub-小鱼干 hacker 这个词,大多数理解为黑客,而维基百科对其的定义为--黑客(Hacker)是指对设计.編程和计算机科学方面具高度理解的人,在本文中 hacker 主要 ...
- JMH-大厂是如何使用JMH进行Java代码性能测试的?必须掌握!
Java 性能测试难题 现在的 JVM 已经越来越为智能,它可以在编译阶段.加载阶段.运行阶段对代码进行优化.比如你写了一段不怎么聪明的代码,到了 JVM 这里,它发现几处可以优化的地方,就顺手帮你优 ...