Java对象大小:size和retained size
最近看到网上很多文章讲如何计算java对象的大小(size),很多观点不敢苟同。
这是其中一篇比较靠前的文章,写的也比较全面:
http://blog.csdn.net/iter_zc/article/details/41822719/
认真拜读了一下,有些收获,也有一些疑问。
按照“字节对齐”的理论,所有java对象的大小应该是8的整数倍,且对象头会有8+4=12个字节
下面写了两个类进行验证:

代码中SizeOfAgent是文中讲到的通过Instrumentation.getObjectSize()计算对象大小的方法
两个对象大小确实是8的倍数,其中b.size的运行结果跟其文中讲到是一样的
b.size = 8(_mark) + 4(oop指针) + 4(i1) + 4(i2) + 1(b1) + 1(b2) + 1(b3) + 1(padding) + 4(str) + 4(obj) = 32
但a.size就不对了,按照该理论
a.size= 8(_mark) + 4(oop指针) + 4(a) + 4(strB) + 4(padding) = 24
但实际运行结果是16,带着疑惑去看了一下官方文档:

可以看到,Instrumentation.getObjectSize()返回的是一个估算值。
我认为,既然是估算值,对于学术研究,没什么参考性。其实Java对象大小从概念开始就比较复杂,要不然的话,干脆提供c++那样的sizeOf用就行了,还用整个javaagent来包装Instrumentation来提供
Java对象大小应该从两方面去理解:(1)其本身的大小-size (2)其占用堆的大小-retained
用JVisualVm提供的Heap dump可以来看这两个数值,以下是这两个对象在JVisualVm显示的size

没找到理论依据,我估计是这么计算的
a.size = 8(对象头) + 4(a) + 4(strB) = 16
b.size = 8(对象头) + 4(str) + 4(i1) + 1(b1) + 1(b2) + 4(i2) + 4(obj) + 1(b3) = 27
这个算法总结为 size(object) = 8 + sum(sizeField(x)), x为object所有字段
(1)8是对象头,具体是什么,没研究过
(2)sizeField对于简单类型的字段(byte/short/int/long...),返回(1/2/4/8...),对于对象类型的字段,返回4(可以理解为一个指针地址的大小)
读者可以写些其他结构来验证这个公式
那么retained又怎么算呢,首先看下这个单词的解释
The retained size for an object is the quantity of memory this objects preserves from garbage collection
retained表示一个对象无法被垃圾回收的内存大小,反过来讲就是它被回收后,能释多少内存
同一种类型的对象,其size必然是相同的,但retained size不一定相同
这个很好理解,size只跟类型相关,retained size 跟数据相关,一个对象里面有个String字段是null,另外一个对象里面该字段存的“abc”,内存占用必然不相同
注意:不能简单地认为retained size就是对象本身的size+所有字段的retained size,因为对象里面的一个字段可能被其他对象在引用。
下面来看一段代码

申明了两个类A和B,各有两个对象,通过JVisualVm来看他们的Size和Retained Size(中文版里面叫保留的大小,吐槽一下JDK自带的工具的中文翻译很稀烂):



结论:
- size(object) = 8 + sum(sizeField(x)); x为object所有字段
- sizeField(field) = isPrimitive ? primitiveSize(field) : 4;
- retained(object)= size(object) + sum(retained(x)) ; if x仅被object引用
Java对象大小:size和retained size的更多相关文章
- Shallow Size 和 Retained Size
所有包含Heap Profling功能的工具(MAT, Yourkit, JProfiler, TPTP等)都会使用到两个名词,一个是Shallow Size,另一个是 Retained Size. ...
- Java对象大小计算
这篇说说如何计算Java对象大小的方法.之前在聊聊高并发(四)Java对象的表示模型和运行时内存表示 这篇中已经说了Java对象的内存表示模型是Oop-Klass模型. 普通对象的结构如下,按64位机 ...
- 两种计算Java对象大小的方法
之前想研究一下unsafe类,碰巧在网上看到了这篇文章,觉得写得很好,就转载过来.原文出处是: http://blog.csdn.net/iter_zc/article/details/4182271 ...
- Java虚拟机14:Java对象大小、对象内存布局及锁状态变化
一个对象占多少字节? 关于对象的大小,对于C/C++来说,都是有sizeof函数可以直接获取的,但是Java似乎没有这样的方法.不过还好,在JDK1.5之后引入了Instrumentation类,这个 ...
- Java虚拟机18:Java对象大小、对象内存布局及锁状态变化
一个对象占多少字节? 关于对象的大小,对于C/C++来说,都是有sizeof函数可以直接获取的,但是Java似乎没有这样的方法.不过还好,在JDK1.5之后引入了Instrumentation类,这个 ...
- java调优随记-java对象大小
在java中,基本数据类型的大小是固定.但是java对象的大小是不固定的,需要通过计算. 在java中,一个空对象(没有属性和方法的对象)在堆中占用8byte,比如 Object obj = new ...
- java对象大小
Java对象的内存布局:对象头(Header),实例数据(Instance Data)和对齐填充(Padding) 对象头在32位系统上占用8B,64位系统上占16B. 无论是32位系统还是64位系统 ...
- GC之二--GC是如何回收时的判断依据、shallow(浅) size、retained(保留) size、Deep(深)size
回到问题“为何会内存溢出?”. 要回答这个问题又要引出另外一个话题,既什么样的对象GC才会回收? 一.对象存活方式判断方法 在上一篇文章<GC之一--GC 的算法分析.垃圾收集器.内存分配策略介 ...
- jvm详情——2、Java对象在jvm中的大小
Java对象的大小 基本数据的类型的大小是固定的,这里就不多说了.对于非基本类型的Java对象,其大小就值得商榷.在Java中,一个空Object对象的大小是8byte,这个大小只是保存堆中一个没有任 ...
随机推荐
- Jquery $(this).attr和$(this).val用法示例
以下是个人心得整理,有兴趣朋友可以参考参考 $(this).attr(key); 获取节点属性名为key的值,相当于getAttribute(key)方法 $(this).attr(key,value ...
- hdu3416 Marriage Match IV(最短路+网络流)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3416 题意: 给出含n个点.m条有向边的图,每条边只能走一次,给出起点和终点,求起点到终点的最短路径有 ...
- CodeForces 432C Prime Swaps
Description You have an array a[1], a[2], ..., a[n], containing distinct integers from 1 to n. Your ...
- 部分iphone手机上的div的点击事件无效
最近在做一个手机移动端的项目,Andrio手机和部分iphone手机上点击事件都是好的,只有在老的型号上的iphone手机上点击事件无效果. 后来在网上查了很多资料,发现有加样式cursor:poin ...
- 粗略使用.NetCore2.0自带授权登陆Authorize
上篇有朋友提及到如果nginx做集群后应该还会有下一篇文章主讲session控制,一般来说就是登陆:本篇分享的内容不是关于分布式session内容,而是netcore自带的授权Authorize,Au ...
- [2014-08-18]初尝 AspNet vNext On Mac
网上关于AspNet vNext的介绍已经非常多,本文不再赘述,仅记录下Mac环境的几点注意事项. 环境 OSX 10.9.4 Mono 3.6.1 Kvm 1.0.0-alpha4-10285 mo ...
- js动态获取时间的方式
列子的时间是这样实现的."2017/7/25 下午10:27:11 星期二" 列子中有一个div用来放时间. 每隔1s执行一次函数,秒就会变. function showTime( ...
- 如何快速的理解JavaScript闭包?
先看问题 1. 在js中的作用域是什么? 作用域就是作用范围,作用空间.作用域分为全局作用域和局部作用域.(这个东西大家都明白) 如果把局部作用域比作一个国家,那么全局作用域就是地球,地球上除了那个国 ...
- Entity Framework Core Like 查询揭秘
在Entity Framework Core 2.0中增加一个很酷的功能:EF.Functions.Like(),最终解析为SQL中的Like语句,以便于在 LINQ 查询中直接调用. 不过Entit ...
- jvm系列 (五) ---类的加载机制
类的加载机制 目录 jvm系列(一):jvm内存区域与溢出 jvm系列(二):垃圾收集器与内存分配策略 jvm系列(三):锁的优化 jvm系列 (四) ---强.软.弱.虚引用 我的博客目录 什么是类 ...