3 Java对象的内存布局以及对象的访问定位

九路 等级 792 0 0

先来看看Java对象在内存中的布局

一 Java对象的内存布局

在HotSpot虚拟机中,对象在内存中的布局分为3个区域 对象头(Header) Mark Word(在32bit和64bit虚拟机上长度分别为32bit和64bit)存储对象自身的运行时数据,包括哈希码,GC分代年龄,锁状态标志,线程持有的锁,偏向线程ID,偏向时 间戳等

  • 类型指针 即对象指向它的类元数据的指针,虚拟机通过这个指针来确定这个对象是哪个类的实例.但是并不是所有类型虚拟机实现都必须在对象数据上保留类型指针,如果对象是一个java数组,那在对象头中还必须有一块用于记录数组长度的数据,因为虚拟机可以通过普通java对象的元数据信息确定Java对象的大小,但是从数组的元数据中却无法确定数据的大小

  • 实例数据(Instance Data) 对象真正存储信息的地方,也是代码中所定义的各种类型的字段内容.无论是继承下来的,还是子类中定义的,都需要记录起来.

  • 对象填充(Padding) 并不是必然存在的,也没有特别的含义仅仅起到点位符的作用.由于HotSpot的自动管理内存系统要求对象起始地址是8字节的整数倍,换句话说就是对象的大小必须是8字节的整数倍,而对象头正好是8字节的倍数(1倍或者2倍),因此当对象实例部分没有对齐时,就需要通过对齐填充来补全 知道了Java对象的内存布局,那么如何定位到对象呢?

二 Java对象的访问定位

对立对象是为了使用对象.Java程序需要通过在栈上的reference数据操作堆上的具体对象. 由于reference类型在Java虚拟机规范中只规定了一个指向对象的引用,并没有定义这个引用应该通过何种方式去定位,访问堆中的对象的具体位置,所以对象的访问方式取决于虚拟机的实现而定的. 目前主流的访问对象的方式有两种

句柄

  • 定义: Java堆中将会划分出一块内存来作为句柄池,refenerce中存储的就是对象的句柄的地址,而句柄中包 含了对象实例数据与类型数据各自的具体地址信息
  • 优点 : 最大的好处就是reference中存储的是稳定的句柄的地址,在对象被移动(垃圾回收时移动对象是很常见的行为)时只会改变句柄中的实例数据的地址,而reference本身不需要修改

直接指针

  • 定义 : reference中存储直接对象的地址,但是必须考虑放置访问类型数据的相关信息
  • 优点 : 访问速度快,节省了一次指针定位的时间开销

注:HotSpot使用第2种方法,但是使用句柄的方法也很常见

这两种对象访问用两张图表示如下: 第一种: 使用句柄方式: 3 Java对象的内存布局以及对象的访问定位

第二种:直接指针方式: 3 Java对象的内存布局以及对象的访问定位

以上两张图明确的表示出句柄和指针两种方法.

收藏
评论区

相关推荐

3 Java对象的内存布局以及对象的访问定位
先来看看Java对象在内存中的布局 一 Java对象的内存布局 在HotSpot虚拟机中,对象在内存中的布局分为3个区域 对象头(Header) Mark Word(在32bit和64bit虚拟机上长度分别为32bit和64bit)存储对象自身的运行时数据,包括哈希码,GC分代年龄,锁状态标志,线程持有的锁,偏向线程ID,偏向时 间戳等 类型指
JAVA回调机制(CallBack)之小红是怎样买到房子的??
JAVA回调机制CallBack 序言最近学习java,接触到了回调机制(CallBack)。初识时感觉比较混乱,而且在网上搜索到的相关的讲解,要么一言带过,要么说的比较单纯的像是给CallBack做了一个定义。当然了,我在理解了回调之后,再去看网上的各种讲解,确实没什么问题。但是,对于初学的我来说,缺了一个循序渐进的过程。此处,将我对回调机制的个人理解,按
JAVA 基础3
一.数组的概念 ======= 数组可以看成是多个数据类型的集合,是对这些数据进行统一的管理; 数组的变量是引用类型,数组本身是对象,数组中的每个元素相当于该对象的成员变量; 数组的元素可以是任何数据类型,包括基础数据类型和引用类型; 二.数组的声明方式 ========= 数据类型 + \[ \] + 数组名称 = new + 数据类型
JDK的3个bug
**1.Annotation引用非空enum数组返回空数组** 首次发现时的环境:JDK 1.8 首次发现所在项目:[APIJSON](https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fgithub.com%2FTommyLemon%2FAPIJSON) 测试用例: publi
Java(3)
面向对象编程思想:抽象  继承  多态  封装 ----------------------- ### 对象:万事万物皆对象.  类:把具有相同属性和方法的对象抽象出来形成的几何体! 类是对象的抽象,对象是类的具体! ### **如何描述一个类** 1. 属性(属性不初始化时也有初始值,会自动初始化,整形为0  小数型为0.0    boolea
Java周总结3
撰写第三周课程总结及实验报告(一) **Java实验报告** 班级 计科一班     学号 20188375     姓名 汤云云    完成时间 评分等级 **实验一 Java开发环境与简单Java程序** 一、 **实验目的** (1) 熟悉JDK开发环境 (2) 熟练掌握结构化程序设计方法 二、 **实验内容** 1. 打印输
Java并发机制(3)
[Java并发编程:volatile关键字解析](https://www.oschina.net/action/GoToLink?url=http%3A%2F%2Fwww.cnblogs.com%2Fdolphin0520%2Fp%2F3920373.html)及内存模型 ===========================================
Java并发系列3
考虑这样的场景:我司出了一款新游戏,因模式新颖、宣传到位,导致游戏开服火爆,每次新开一个服务器就会一下涌入大量玩家。假如一个线路服务器的承载力上限是5000,那么我们该通过什么机制进行资源调配呢? 比较容易想到的方法就是给每个玩家发许可证,同时一个服务器的许可证上限为5000,这样的话,许可证超出上限则玩家需要排队。 今天我们讲的并发工具就如同代码层
java例题_21 求 1+2!+3!+...+20!的和
1 /*21 【程序 21 求阶乘】 2 题目:求 1+2!+3!+...+20!的和 3 程序分析:此程序只是把累加变成了累乘。 4 */ 5 6 /*分析 7 * 1、汲取上一题的教训,这么大的数字,long类型 8 * 2、for循环,两层,一层控制1~20,另
java入门(3)
函数和方法 ----- 如果我们经常要进行一些相似的处理过程,就可以把这个处理过程封装为**函数**。 函数可以被多次重复调用,从而实现代码重用和隔离的目的。 在面向对象的语言中,函数经常和对象绑定在一起,为区分起见,这时它被称为**方法**。 因为java是完全面向对象的,函数必须从属于某个类。所以java中的函数都被称为方法。 如果方法前以 s
java多线程的3种实现方式
### 多线程相关的问题 > **1.什么是进程?** > > ​ 正在执行的程序 > > **2.什么是线程?** > > ​ 进程的子单位,一个能够完成独立功能的执行路径 > > **3.为什么需要开启多线程?** > > * 当执行某些耗时操作的任务的时候需要开启多线程,防止线程阻塞 > * 能够让两个任务看起来像是在同时执行 >
java学习笔记3
1  创建引用类型变量公式     数据类型  变量名 = new 数据类型();     变量名.方法名(); 2  Scanner 类的使用 ![](https://oscimg.oschina.net/oscnet/f0aaacf3774ded91479f8e42c680794aa8c.jpg) ![](https://oscimg.oschi
3、python的传入参数
转载:https://blog.csdn.net/abc\_12366/article/details/79627263 1、位置参数: ======= def func(a, b): print(a+b) func(1, 2) #3 2、默认参数,_默认参数就是在调用函数的时候使用一些包含默认值的参数_ ====================
3、MongoDB的使用
##1、开启Mongodb 如图进入D盘: ![](https://oscimg.oschina.net/oscnet/850cf1762f99053852417636f1012b6a36c.png) D:\\aaa\\db\\mongodb3.4.15\\bin D:\\aaa\\db\\mongodb3.4.15\\data 再开一个cmd: D:\
SparkSQL的3种Join实现
引言 Join是SQL语句中的常用操作,良好的表结构能够将数据分散在不同的表中,使其符合某种范式,减少表冗余、更新容错等。而建立表和表之间关系的最佳方式就是Join操作。 对于Spark来说有3中Join的实现,每种Join对应着不同的应用场景: Broadcast Hash Join :适合一张较小的表和一张大表进行join Shuffle Hash