打印Java对象头

对象头形式

JVM中对象头的方式有以下两种(以32位JVM为例)普通对象|--------------------------------------------------------------|

| Object Header (64 bits) |

|------------------------------------|-------------------------|

| Mark Word (32 bits) | Klass Word (32 bits) |

|------------------------------------|-------------------------|数组对象|---------------------------------------------------------------------------------|

| Object Header (96 bits) |

|--------------------------------|-----------------------|------------------------|

| Mark Word(32bits) | Klass Word(32bits) | array length(32bits) |

|--------------------------------|-----------------------|------------------------|对象头的组成 Mark Word

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

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

| Mark Word (32 bits) | State |

|-------------------------------------------------------|--------------------|

| identity_hashcode:25 | age:4 | biased_lock:1 | lock:2 | Normal |

|-------------------------------------------------------|--------------------|

| thread:23 | epoch:2 | age:4 | biased_lock:1 | lock:2 | Biased |

|-------------------------------------------------------|--------------------|

| ptr_to_lock_record:30 | lock:2 | Lightweight Locked |

|-------------------------------------------------------|--------------------|

| ptr_to_heavyweight_monitor:30 | lock:2 | Heavyweight Locked |

|-------------------------------------------------------|--------------------|

| | lock:2 | Marked for GC |

|-------------------------------------------------------|--------------------||--------------------------------|-----------------------|------------------------|

| biased_lock | lock | state |

|--------------------------------|-----------------------|------------------------|

| 0 | 01 | 无锁 |

|--------------------------------|-----------------------|------------------------|

| 1 | 01 | 偏向锁 |

|--------------------------------|-----------------------|------------------------|

| | 00 | 轻量级锁 |

|--------------------------------|-----------------------|------------------------|

| | 10 | 重量级锁 |

|--------------------------------|-----------------------|------------------------|

| | 11 | GC |

|--------------------------------|-----------------------|------------------------|identity_hashcode:对象标识Hash码,采用延迟加载技术。当对象使用HashCode()计算后,并会将结果写到该对象头中。当对象被锁定时,该值会移动到线程Monitor中。

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

biased_lock:偏向锁标记,为1时表示对象启用偏向锁,为0时表示对象没有偏向锁。

lock: 锁状态标记位,该标记的值不同,整个mark word表示的含义不同。

thread:持有偏向锁的线程ID和其他信息。这个线程ID并不是JVM分配的线程ID号,和Java Thread中的ID是两个概念。

epoch:偏向时间戳。

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

ptr_to_heavyweight_monitor:指向线程Monitor的指针。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指针等。array length

如果对象是一个数组,那么对象头还需要有额外的空间用于存储数组的长度,这部分数据的长度也随着JVM架构的不同而不同:32位的JVM上,长度为32位;64位JVM则为64位。64位JVM如果开启+UseCompressedOops选项,该区域长度也将由64位压缩至32位。打印对象头 注:以下测试我本机是64位,无锁:unused:25 | identity_hashcode:31 | unused:1 | age:4 | biased_lock:1 | lock:2;偏向锁:thread:54 | epoch:2 | unused:1 | age:4 | biased_lock:1 | lock:2

引入打印工具dependency

groupIdorg.openjdk.jol/groupId

artifactIdjol-core/artifactId

version0.8/version

scopetest/scope

/dependency

代码:static class A {

boolean flag = false;

}

public static void main(String[] args){

A a = new A();

System.out.println(ClassLayout.parseInstance(a).toPrintable());

}

输出结果:...A object internals:

OFFSET SIZE TYPE DESCRIPTION VALUE

0 4 (object header) 01 00 00 00 (00000001 00000000 00000000 00000000) (1)

4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)

8 4 (object header) 93 c2 00 f8 (10010011 11000010 00000000 11111000) (-134167917)

12 1 boolean A.flag false

13 3 (loss due to the next object alignment)

Instance size: 16 bytes

Space losses: 0 bytes internal + 3 bytes external = 3 bytes total

最后两位是lock01,表示无锁或者是偏向锁。则倒数第三位是biased_lock0,标识当前对象无锁。00000 0 01JVM启动时会进行一系列的复杂活动,比如装载配置,系统类初始化等等。在这个过程中会使用大量synchronized关键字对对象加锁,且这些锁大多数都不是偏向锁。为了减少初始化时间,JVM默认延时加载偏向锁。这个延时的时间大概为4s左右,具体时间因机器而异。当然我们也可以设置JVM参数 -XX:BiasedLockingStartupDelay=0 来取消延时加载偏向锁。

修改代码:public static void main(String[] args) throws InterruptedException {

Thread.sleep(5000);

A a = new A();

System.out.println(ClassLayout.parseInstance(a).toPrintable());

}

输出结果:...A object internals:

OFFSET SIZE TYPE DESCRIPTION VALUE

0 4 (object header) 05 00 00 00 (00000101 00000000 00000000 00000000) (5)

4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)

8 4 (object header) 93 c2 00 f8 (10010011 11000010 00000000 11111000) (-134167917)

12 1 boolean A.flag false

13 3 (loss due to the next object alignment)

Instance size: 16 bytes

Space losses: 0 bytes internal + 3 bytes external = 3 bytes total

最后两位是lock01,表示无锁或者是偏向锁。则倒数第三位是biased_lock1,标识当前对象可偏向(Thread的值还是0)。00000 0 01前面说过,identity_hashcode对象标识Hash码,采用延迟加载技术。

修改代码public static void main(String[] args) throws InterruptedException {

Thread.sleep(5000);

A a = new A();

System.out.println(System.identityHashCode(a));

System.out.println(ClassLayout.parseInstance(a).toPrintable());

}

输出结果:777874839

A object internals:

OFFSET SIZE TYPE DESCRIPTION VALUE

0 4 (object header) 01 97 6d 5d (00000001 10010111 01101101 01011101) (1567463169)

4 4 (object header) 2e 00 00 00 (00101110 00000000 00000000 00000000) (46)

8 4 (object header) 93 c2 00 f8 (10010011 11000010 00000000 11111000) (-134167917)

12 1 boolean A.flag false

13 3 (loss due to the next object alignment)

Instance size: 16 bytes

Space losses: 0 bytes internal + 3 bytes external = 3 bytes total

00000001标识无锁状态 ,777874839十进制转二进制结果是2e 5d 6d 97

打印Java对象头 相关文章

深入了解Java锁

继 打印Java对象头 ,我们再深入探索一下Java锁。无锁状态我们就不说了,下面我们一一打印偏向锁、轻量锁,重量锁的对象头。 打印偏向锁 修改代码: public static void main(String[] args) throws InterruptedException { Thread.sleep(5000); A a = new A

java jdbc连接mysql数据库实现增删改查操作

原文链接:https://www.jb51.net/article/88300.htm jdbc相信大家都不陌生,只要是个搞java的,最初接触j2ee的时候都是要学习这么个东西的,谁叫程序得和数据库打交道呢!而jdbc就是和数据库打交道非常基础的一个知识,也是比较接近底层的,在实际的工作中大

运维:生产日志重复打印了,赶紧来看看~

一、前言 在一次生产环境发布后,运维对我说,你这个日志打印了两遍,你看一下,我很好奇,打印了两遍,本地和测试都没有这个问题啊,然后运维就发了下面两个文件给我,一看还真是,日志怎么打印了两遍 启动也是日志会打印两遍 二、解决方案 刚开始是看资料

Java面试特殊知识点总结 part1

并发与多线程main方法里没有创建新的线程,执行main方法一共需要几个线程? 可以使用 ManagementFactory 的 getThreadMXBean 方法获取 ThreadMXBean 信息,进而获取线程信息进行查看。代码: package Exercise;import java.lang.management.ManagementFactory

万字长文总结JAVA几种常见的编码格式和乱码原因分析

你知道的越多,不知道的就越多,业余的像一棵小草! 你来,我们一起精进!你不来,我和你的竞争对手一起精进! 编辑:业余草developer.ibm.com/zh/articles/j-lo-chinesecoding/推荐:https://www.xttblog.com/p=5151 万字长文总结JAVA几种常见的编码格式和乱

javascript之date

1 Date日期 1.1 创建日期 /* 当前时间 */new Date();/* any certain date *//* new Date(year,month[,day[,hour[,minutes[,seconds[,milliseconds]]]]]) */new Date(1978,11);//1978-12-01 00:00:00/* Date函数中月份是‘0-11’,所以显示的月份要比代码中的

Java 框架领域佼佼者 Spring 初识篇

Spring 简介 Spring 是一个轻量级的 Java 开发框架,它是为了解决企业应用开发的复杂性而创建的,常年雄踞于企业开发必选框架之首。 Spring 的核心是控制反转( IoC )和面向切面编程( AOP )。简单来说, Spring 是一个分层的 Java EE 一站式轻量级开源框

Java 项目管理工具 Maven

为什么使用项目管理工具 由于 Java 的生态非常丰富,无论你想实现什么功能,都能找到对应的工具类,这些工具类都是以 jar 包的形式出现的,例如 Spring,SpringMVC、MyBatis、数据库驱动,等等,都是以 jar 包的形式出现的,jar 包之间会有关联,在使用一个

Java 中使用 Jersey 实现上传文件(附加密和解密)

Jersey 简介 Jersey 是开源的 RESTful 框架,实现了 JAX-RS 规范,提供了更多的特性和工具, 可以进一步地简化 RESTful service 和 client 开发,与 Struts 类似,它同样可以和 Hibernate 、 Spring 框架整合。此处使用它实现文件上传功能。 引入依赖 在 pom

详解 Java I/O 流

概述 Java 的 I/O 大概可以分成以下几类: 磁盘操作:File 字节操作:InputStream 和 OutputStream 字符操作:Reader 和 Writer 对象操作:Serializable 网络操作:Socket 新的输入/输出:NIO 磁盘操作 File 类可以用于表示文件和目录的信息,但是它不表示文

java打印对象头信息_打印Java对象头相关推荐

  1. java读取mp3文件信息_用JAVA读取MP3文件的标签信息

    突然看到网上有人在用JavaScript来读取MP3中ID3信息.详细请看! 我也在网上搜索了用Flex写的实现同样的功能的.详细请看! 但是我比较熟悉Java.所以也在网上搜索到了用Java实现的读 ...

  2. java 输出ssl握手信息_使用Java的SSL握手错误

    我正在尝试使用SSL证书将Java客户端与JMX服务器连接 . 但遗憾的是,此连接会产生SSL握手错误 . 当我尝试使用 -Djavax.net.debug=all 标志进行调试时,我在java客户端 ...

  3. 【源码+图片素材】Java王者荣耀游戏开发_开发Java游戏项目【王者荣耀】1天搞定!!!腾讯游戏_Java课程设计_Java实战项目_Java初级项目

    王者荣耀是当下热门手游之一,小伙伴们是否想过如何制作一款属于自己的王者荣耀游戏呢? 本课程讲解了一个王者荣耀游戏的详细编写流程,即使你是刚入门Java的新手,只要你简单掌握了该游戏所需要的JavaSE ...

  4. Java毕设项目诊所信息管理系统(java+VUE+Mybatis+Maven+Mysql)

    Java毕设项目诊所信息管理系统(java+VUE+Mybatis+Maven+Mysql) 项目运行 环境配置: Jdk1.8 + Tomcat8.5 + Mysql + HBuilderX(Web ...

  5. Http头信息(二)——请求头信息(一)

    文章目录 前言 1. `Accept` 2. `Accept-Charset` 3. `Accept-Encoding` 4. `Accept-Language` 5.`Authorization` ...

  6. java打印args的内容_解决java main函数中的args数组传值问题

    这几天面试中有遇到关于main数组中的args数组传值的问题,一般是从命令提示符中传值,也可以直接在java代码中赋值. 而且这个数组的长度是动态的,根据传值的个数确定数组的长度. 1.从命令提示符中 ...

  7. java打印两个小人_[原创]Java画小人与阶梯问题的解答

    package test; /** #Python源代码: #By:Cat73 QQ 1901803382 #2014年7月22日19:33:12 #画图函数 width:台阶的宽度(至少为4) hi ...

  8. scanner 获取控制台信息_关于java.util.scanner:如何使用Java中的Scanner类从控制台读取输入?...

    如何使用Scanner类从控制台读取输入? 像这样: System.out.println("Enter your username:"); Scanner = input(); ...

  9. java 如何循环执行一个对象_一个Java对象到底有多大?

    编写Java代码的时候,大多数情况下,我们很少关注一个Java对象究竟有多大(占据多少内存),更多的是关注业务与逻辑.但是殊不知,在我们不经意间,大量的内存被无形地浪费了. 一个Java对象到底有多大 ...

最新文章

  1. 【C++】C/C++ 中多态情形下的虚函数表查看方法
  2. JavaWeb 入门篇(3)ServletContext 详解 具体应用
  3. batch normalization_常用的 Normalization 方法:BN、LN、IN、GN
  4. mysql 没有mysql库_MySQL安装之后没有MySQL数据库的原因
  5. Java PECS
  6. pre2-flink单机部署与job提交
  7. 完整机器学习项目的流程
  8. 我的第一份外包经历及所得
  9. 关于Dll、Com组件、托管dll和非托管dll的理解
  10. 15个最佳jQuery的翻页书效果的例子
  11. 如何通过 Shell 监控异常等待事件和活跃会话
  12. 35、IFE任务34——听指令的小方块(二)
  13. ORACLE数据库新增表空间的数据存储文件
  14. exfat最佳单元大小_回音壁构造和单元相关的个人看法
  15. Linux环境下FFMPEG的安装与配置
  16. 不同SIP客户端使用说明
  17. 用Python基础做的游戏角色管理系统
  18. prlooks插件下载_ae looks插件下载
  19. android系统设置默认字体,如何获取Android设备的默认字体?
  20. java清除session_退出页面自动清除java session方法

热门文章

  1. CSS3:text-shadow属性
  2. Android Binder框架实现之Parcel详解之基本数据的读写
  3. 前端百题斩[001]——typeof和instanceof
  4. 惠州生物实验室设计细节,建设大纲
  5. 总结:三种昆虫天敌标本的制作方法
  6. 1595:Symmetry
  7. SequoiaDB巨杉数据库SequoiaFS挂载目录
  8. 在mac上关闭microsoft的自动更新
  9. com.alibaba.dubbo.remoting.TimeoutException异常的解决方法
  10. COJ1981-小M的魔术表演