JVM系列之:详解java object对象在heap中的结构
简介
在之前的文章中,我们介绍了使用JOL这一神器来解析java类或者java实例在内存中占用的空间地址。
今天,我们会更进一步,剖析一下在之前文章中没有讲解到的更深层次的细节。一起来看看吧。
对象和其隐藏的秘密
java.lang.Object大家应该都很熟悉了,Object是java中一切对象的鼻祖。
接下来我们来对这个java对象的鼻祖进行一个详细的解剖分析,从而理解JVM的深层次的秘密。
工具当然是使用JOL:
@Slf4j
public class JolUsage {
@Test
public void useJol(){
log.info("{}", VM.current().details());
log.info("{}", ClassLayout.parseClass(Object.class).toPrintable());
log.info("{}", ClassLayout.parseInstance(new Object()).toPrintable());
}}
代码很简单,我们打印JVM的信息,Object class和一个新的Object实例的信息。
看下输出:
从上面的结果我们知道,在64位的JVM中,一个Object实例是占用16个字节。
因为Object对象中并没有其他对象的引用,所以我们看到Object对象只有一个12字节的对象头。剩下的4个字节是填充位。
Object对象头
那么这12字节的对象头是做什么用的呢?
如果想要深入了解这12字节的对象头,当然是要去研读一下JVM的源码:src/share/vm/oops/markOop.hpp。
有兴趣的小伙伴可以去看看。如果没有兴趣,没关系,这里给大家一个张总结的图:
javaObject对象的对象头大小根据你使用的是32位还是64位的虚拟机的不同,稍有变化。这里我们使用的是64位的虚拟机为例。
Object的对象头,分为两部分,第一部分是Mark Word,用来存储对象的运行时数据比如:hashcode,GC分代年龄,锁状态,持有锁信息,偏向锁的thread ID等等。
在64位的虚拟机中,Mark Word是64bits,如果是在32位的虚拟机中Mark Word是32bits。
第二部分就是Klass Word,Klass Word是一个类型指针,指向class的元数据,JVM通过Klass Word来判断该对象是哪个class的实例。
且慢!
有的小伙伴可能发现了问题,之前我们用JOL解析Object对象的时候,Object head大小是12字节,也就是96bits,这里怎么写的是128bits?
没错,如果没有开启COOPs就是128bits,如果开启了COOPs,那么Klass Word的大小就从64bits降到了32bits。
还记得我们之前讲的COOPs吗?
COOPs就是压缩对象指针技术。
对象指针用来指向一个对象,表示对该对象的引用。通常来说在64位机子上面,一个指针占用64位,也就是8个字节。而在32位机子上面,一个指针占用32位,也就是4个字节。
实时上,在应用程序中,这种对象的指针是非常非常多的,从而导致如果同样一个程序,在32位机子上面运行和在64位机子上面运行占用的内存是完全不同的。64位机子内存使用可能是32位机子的1.5倍。
而压缩对象指针,就是指把64位的指针压缩到32位。
怎么压缩呢?64位机子的对象地址仍然是64位的。压缩过的32位存的只是相对于heap base address的位移。
我们使用64位的heap base地址+ 32位的地址位移量,就得到了实际的64位heap地址。
对象指针压缩在Java SE 6u23 默认开启。在此之前,可以使用-XX:+UseCompressedOops来开启。
数组对象头
java中有一个非常特别的对象叫做数组,数组的对象头和Object有什么区别吗?
我们用JOL再看一次:
log.info("{}",ClassLayout.parseClass(byte[].class).toPrintable());
log.info("{}",ClassLayout.parseInstance("www.flydean.com".getBytes()).toPrintable());
上面的例子中我们分别解析了byte数组的class和byte数组的实例:
看到区别了吗?我们发现数组的对象头是16字节,比普通对象的对象头多出了4个字节。这4个字节就是数组的长度。
整个对象的结构
好了,写到这里我们来总结一下,java对象的结构可以分为普通java对象和数组对象两种:
数组对象在对象头中多了一个4字节的长度字段。
大家看到最后的字节是padding填充字节,为什么要填充呢?
因为JVM是以8字节为单位进行对其的,如果不是8字节的整数倍,则需要补全。
更多精彩内容
1 | |
2 | |
3 | |
喜欢本篇文章?帮忙点个「在看」再走吧
本文分享自微信公众号 - 程序那些事(flydean-tech)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
JS明明写的请求是并行,为何仍然串行请求?
环境 测试环境:electron + vue + axios 需求 想要做并行请求(比如爬虫)需要尽量快的请求页面。 假如一次发出请求到返回所需时间为100ms: 方案1(串行):请求一次接口等待返回处理结果后继续下一次请求。这样会受制于请求的速度,假如请求100次那么需要总时间为100ms * 100 = 10000ms 方案2(并行):利用Promise,同时发起多个请求,但不等待每个请求结束。而是Promise.all等待其全部结束再进行处理。假如请求100次那么需要总时间为100ms * 1= 100ms 可以看出速度有极大的提升,理论上(实际需要看机器配置和网络带宽情况)无论多少请求都只需要100ms。 并行实现 我们的需求就是方案2的并行实现。所以如下实现: async t () { const time1 = new Date().getTime() / 1000 const task = [] for (let i=0; i < 100; i++){ task.push(this.t1()) // 发起请求 } await Promise.all(t...
- 下一篇
【技术综述】基于3DMM的三维人脸重建技术总结
基于图像的人脸三维重建在人脸分析与娱乐领域里有巨大的应用场景,同时它也可以用于提升人脸关键点检测,人脸识别,人脸编辑等很多任务。本文重点介绍其中基于3DMM模型的核心技术及其研究进展。 作者&编辑 | 言有三 1. 什么是人脸三维重建 人脸三维重建就是建立人脸的三维模型,它相对于二维人脸图像多了一个维度,在电影,游戏等领域应用广泛。目前获取人脸三维模型的方法主要包括三种,软件建模,仪器采集与基于图像的建模。 (1) 软件建模作为最早的三维建模手段,现在仍然是最广泛地在电影,动漫行业中应用。顶顶大名的3DMax就是典型代表,作品如下图。 (2) 由于手工建模耗费大量的人力,三维成像仪器也得到了长期的研究和发展。基于结构光和激光仪器的三维成像仪是其中的典型代表,我们熟知的iphoneX中的人脸识别就是基于结构光进行三维人脸重建,正因如此才有iphonex中的三维人脸表情包。这些基于仪器采集的三维模型,精度可达毫米级,是物体的真实三维数据,也正好用来为基于图像的建模方法提供评价数据库。不过由于仪器的成本太高,一般的用户是用不上了。 (3) 基于图像的建模技术(image base...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- CentOS8编译安装MySQL8.0.19
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- CentOS6,CentOS7官方镜像安装Oracle11G
- CentOS7,8上快速安装Gitea,搭建Git服务器
- SpringBoot2全家桶,快速入门学习开发网站教程
- CentOS6,7,8上安装Nginx,支持https2.0的开启
- Docker安装Oracle12C,快速搭建Oracle学习环境
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- Hadoop3单机部署,实现最简伪集群