java 64位对象头_Java对象头详解

Java对象头详解

由于Java面向对象的思想,在JVM中需要大量存储对象,存储时为了实现一些额外的功能,需要在对象中添加一些标记字段用于增强对象功能,这些标记字段组成了对象头。

1.对象头形式

JVM中对象头的方式有以下两种(以32位JVM为例):

1.1.普通对象

1.2.数组对象

2.对象头的组成

2.1.Mark Word

这部分主要用来存储对象自身的运行时数据,如hashcode、gc分代年龄等。mark word的位长度为JVM的一个Word大小,也就是说32位JVM的Mark word为32位,64位JVM为64位。

为了让一个字大小存储更多的信息,JVM将字的最低两个位设置为标记位,不同标记位下的Mark Word示意如下:

其中各部分的含义如下:

lock:2位的锁状态标记位,由于希望用尽可能少的二进制位表示尽可能多的信息,所以设置了lock标记。该标记的值不同,整个mark word表示的含义不同。

biased_locklock状态

0

01

无锁

1

01

偏向锁

0

00

轻量级锁

0

10

重量级锁

0

11

GC标记

biased_lock:对象是否启用偏向锁标记,只占1个二进制位。为1时表示对象启用偏向锁,为0时表示对象没有偏向锁。

age:4位的Java对象年龄。在GC中,如果对象在Survivor区复制一次,年龄增加1。当对象达到设定的阈值时,将会晋升到老年代。默认情况下,并行GC的年龄阈值为15,并发GC的年龄阈值为6。由于age只有4位,所以最大值为15,这就是-XX:MaxTenuringThreshold选项最大值为15的原因。

identity_hashcode:25位的对象标识Hash码,采用延迟加载技术。调用方法System.identityHashCode()计算,并会将结果写到该对象头中。当对象被锁定时,该值会移动到管程Monitor中。

thread:持有偏向锁的线程ID。

epoch:偏向时间戳。

ptr_to_lock_record:指向栈中锁记录的指针。

ptr_to_heavyweight_monitor:指向管程Monitor的指针。

64位下的标记字与32位的相似,不再赘述:

2.2.class pointer

这一部分用于存储对象的类型指针,该指针指向它的类元数据,JVM通过这个指针确定对象是哪个类的实例。该指针的位长度为JVM的一个字大小,即32位的JVM为32位,64位的JVM为64位。

如果应用的对象过多,使用64位的指针将浪费大量内存,统计而言,64位的JVM将会比32位的JVM多耗费50%的内存。为了节约内存可以使用选项+UseCompressedOops开启指针压缩,其中,oop即ordinary object pointer普通对象指针。开启该选项后,下列指针将压缩至32位:

每个Class的属性指针(即静态变量)

每个对象的属性指针(即对象变量)

普通对象数组的每个元素指针

当然,也不是所有的指针都会压缩,一些特殊类型的指针JVM不会优化,比如指向PermGen的Class对象指针(JDK8中指向元空间的Class对象指针)、本地变量、堆栈元素、入参、返回值和NULL指针等。

2.3.array length

如果对象是一个数组,那么对象头还需要有额外的空间用于存储数组的长度,这部分数据的长度也随着JVM架构的不同而不同:32位的JVM上,长度为32位;64位JVM则为64位。64位JVM如果开启+UseCompressedOops选项,该区域长度也将由64位压缩至32位。

附:对象头相关的资料

markOop.hpp

CompressedOops

JVM优化之压缩普通对象指针

What is in java object header

Java对象头详解 相关文章

Java-线程

目录 1.线程与进程 进程 线程 区别 2.线程的生命周期 3.创建线程 继承Thread类 实现Runnable接口 关系 关于两种创建线程方法,资源是否共享说法的一点理解 问题:启动一个线程使用run()还是start()方法 1.线程与进程 操作系统中运行的程序,就是一个进程。而

Java同步组件之CountDownLatch,Semaphore

Java同步组件概况 CountDownLatch : 是闭锁,通过一个计数来保证线程是否一直阻塞 Semaphore : 控制同一时间,并发线程数量 CyclicBarrier:字面意思是回环栅栏,通过它可以实现让一组线程等待至某个状态之后再全部同时执行。 ReentrantLock:是一个重入锁,一个线

嘿你要的Java内存模型(JMM)来了!

1、 计算机的硬件内存结构 2、 Java内存模型的背景和定义 3、 Java内存模型 3.1 主内存、工作内存的定义 3.2 内存的交互操作 3.3 JMM缓存不一致问题 4、 Java内存模型的实现 在学习Java内存模型(JMM)前,我们先了解下计算机的硬件内存结构,因为JMM结构就是

Linux入门篇 —— 用户与组管理详解(system-config-users 命令行)

用户与组管理 什么是用户,用户是人吗? 用户是干啥的? 用户账号- 超级管理员: root- 普通用户: ruochen- 系统/程序用户: 系统中为某个程序而产生的用户,这类用户一般不允许登录操作系统 组账号- 定义: 用户的集合- 基本组: 与用户同名的一个组- 附加

20 Spring Cloud Ribbon配置详解

常用配置 1. 禁用 Eureka 当我们在 RestTemplate 上添加 @LoadBalanced 注解后,就可以用服务名称来调用接口了,当有多个服务的时候,还能做负载均衡。 这是因为 Eureka 中的服务信息已经被拉取到了客户端本地,如果我们不想和 Eureka 集成,可以通过下面的

Java随机数-for循环-Scanner-Switchcase

从键盘获取值 java.util.Scanner input = new java.util.Scanner(System.in); java.util.Scanner:是一个扫描仪的类型,是引用数据类型,首字母是大写, 其中java.util是包 input是一个变量名,他表示这个扫描仪 new java.util.Scanner(System.in)是给input

Java运算符-if分支语句

运算符 // 除号:/int num1 = 12;int num2 = 5;int result1 = num1 / num2;System.out.println(result1); //2double result2 = num1 / num2;System.out.println(result2); //2.0double result3 = num1 / num2 + 0.0;System.out.println(result3); //2.0doubl

JavaScript作用域与作用域链

JavaScript作用域 在JavaScript中,变量的作用域有全局作用域和局部作用域两种 1. 全局作用域(Global Scope) 在代码中任何地方都能访问到的对象拥有全局作用域,一般来说以下几种情形拥有全局作用域: (1)最外层函数和在最外层函数外面定义的变量拥有全

Java04:运算符拓展,Javadoc

Java04:运算符拓展,Javadoc 自增自减运算符 ++ -- 自增,自减 一元运算符 ina a = 3; int b = a++;//执行完这行代码后,先给b赋值,在自增int c = ++a;//执行完这行代码前,先自增,再给b赋值 位运算符 A = 0011 1100 B = 0000 1101 AB = 0000 1100 A|B =

Js中的位操作符

Js中的位操作符 JavaScript 的数字类型为双精度 IEEE 754 64 位浮点类型,但是在位运算中位运算符用于 32 位的数字上, 任何的数字操作都将转为 32 位, 运算结果再转化为 Js 数字类型。 描述 所有的按位操作符的操作数都会被转成补码形式的有符号 32 位整数,

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值