背景

目前我们系统的业务代码中大量使用了LocalCache的方式做本地缓存,而且cache的maxSize通常设的比较大,比如10000。我们的业务系统中就使用了size为10000的15个本地缓存,所以最坏情况下将可缓存15万个对象。这会消耗掉不菲的本地堆内存,而至于实际上到底应该设多大容量的缓存、运行时这大量的本地缓存会给堆内存带来多少压力,实际占用多少内存大小,会不会有较高的缓存穿透风险,目前并不方便知悉。考虑到对缓存实际占用内存的大小能有个更直观和量化的参考,需要对运行时指定对象的内存占用进行评估和计算。

要计算Java对象占用内存的大小,首先需要了解Java对象在内存中的实际存储方式和存储格式。

另一方面,大家都了解Java对象的存储总得来说会占用JVM内存的堆内存、栈内存及方法区,但由于栈内存中存放的数据可以看做是运行时的临时数据,主要表现为本地变量、操作数、对象引用地址等。这些数据会在方法执行结束后立即回收掉,不会驻留。对存储空间空间的占用也只是执行函数指令时所必须的空间。通常不会造成内存的瓶颈。而方法区中存储的则是对象所对应的类信息、函数表、构造函数、静态常量等,这些信息在类加载时(按需)只会在方法区中存储一份,不会产生额外的存储空间。因此本文所要讨论的主要目标是Java对象对堆内存的占用。

内存占用计算方法

这里要介绍的是lucene提供的专门用于计算堆内存占用大小的工具类:RamUsageEstimator,maven坐标:

<dependency><groupId>org.apache.lucene</groupId><artifactId>lucene-core</artifactId><version>4.0.0</version>
</dependency>

RamUsageEstimator 就是根据java对象在堆内存中的存储格式,通过计算Java对象头、实例数据、引用等的大小,相加而得,如果有引用,还能递归计算引用对象的大小。RamUsageEstimator的源码并不多,几百行,清晰可读。这里不进行一一解读了。它在初始化的时候会根据当前JVM运行环境、CPU架构、运行参数、是否开启指针压缩、JDK版本等综合计算对象头的大小,而实例数据部分则按照java基础数据类型的标准大小进行计算。思路简单,同时也在一定程度上反映出了Java对象格式的奥秘!

常用方法如下:

//计算指定对象及其引用树上的所有对象的综合大小,单位字节
long RamUsageEstimator.sizeOf(Object obj)//计算指定对象本身在堆空间的大小,单位字节
long RamUsageEstimator.shallowSizeOf(Object obj)//计算指定对象及其引用树上的所有对象的综合大小,返回可读的结果,如:2KB
String RamUsageEstimator.humanSizeOf(Object obj)

使用该第三方工具比较简单直接,主要依靠JVM本身环境、参数及CPU架构计算头信息,再依据数据类型的标准计算实例字段大小,计算速度很快,另外使用较方便。如果非要说这种方式有什么缺点的话,那就是这种方式计算所得的对象头大小是基于JVM声明规范的,并不是通过运行时内存地址计算而得,存在与实际大小不符的这种可能性。

Java对象格式

在HotSpot虚拟机中,Java对象的存储格式也是一个协议或者数据结构,底层是用C++代码定义的。Java对象结构大致如下图所示——

即,Java对象从整体上可以分为三个部分,对象头、实例数据和对齐填充。

对象头(Instance Header):Java对象最复杂的一部分,采用C++定义了头的协议格式,存储了Java对象hash、GC年龄、锁标记、class指针、数组长度等信息。对象头是理解JVM中对象存储方式的最核心的部分,甚至是理解java多线程、分代GC、锁等理论的基础,也是窥探JVM底层诸多实现细节的出发点。

实例数据(Instance Data):这部分数据才是真正具有业务意义的数据,实际上就是当前对象中的实例字段。在VM中,对象的字段是由基本数据类型和引用类型组成的。其所占用空间的大小如下所示:

说明:其中ref表示引用类型,引用类型实际上是一个地址指针,32bit机器上,占用4字节,64bit机器上,在jdk1.6之后,如果开启了指针压缩(默认开启: -XX:UseCompressedOops,仅支持64位机器),则占用4字节。Java对象的所有字段类型都可映射为上述类型之一,因此实例数据部分的大小,实际上就是这些字段类型的大小之和。当然,实际情况可能比这个稍微复杂一点,如字段排序、内部padding以及父类字段大小的计算等。

对齐填充(Padding):VM要求对象大小须是8的整体数,该部分是为了让整体对象在内存中的地址空间大小达到8的整数倍而额外占用的字节数。

如何计算java对象大小相关推荐

  1. 计算 java_两种计算Java对象大小的方法(转)

    原文:http://blog.csdn.net/iter_zc/article/details/41822719 另一篇类似文章:http://www.cnblogs.com/magialmoon/p ...

  2. 如何计算Java对象所占内存的大小

    摘要 本文以如何计算Java对象占用内存大小为切入点,在讨论计算Java对象占用堆内存大小的方法的基础上,详细讨论了Java对象头格式并结合JDK源码对对象头中的协议字段做了介绍,涉及内存模型.锁原理 ...

  3. 聊聊JVM(三)两种计算Java对象大小的方法

    普通对象的结构如下,按64位机器的长度计算 1. 对象头(_mark), 8个字节 2. Oop指针,如果是32G内存以下的,默认开启对象指针压缩,4个字节 3. 数据区 4.Padding(内存对齐 ...

  4. java char占用多少字节_Java虚拟机:Java对象大小、对象内存布局及锁状态变化

    一个对象占多少字节? 关于对象的大小,对于C/C++来说,都是有sizeof函数可以直接获取的,但是Java似乎没有这样的方法.不过还好,在JDK1.5之后引入了Instrumentation类,这个 ...

  5. 两种计算Java对象大小的方法

    之前想研究一下unsafe类,碰巧在网上看到了这篇文章,觉得写得很好,就转载过来.原文出处是: http://blog.csdn.net/iter_zc/article/details/4182271 ...

  6. 如何计算Java对象的大小

    一个对象通常由头和内容组成.想要计算一个对象的大小,我们就需要分别计算头部的大小和内容的大小. 查看一个对象的大小 首先在pom文件中引入apache下面的lucene-core依赖,然后调用对应的s ...

  7. java统计空间占用_如何计算Java对象占用了多少空间?

    在Java中没有sizeof运算符,所以没办法知道一个对象到底占用了多大的空间,但是在分配对象的时候会有一些基本的规则,我们根据这些规则大致能判断出来对象大小. 对象头 对象的头部至少有两个WORD, ...

  8. Java对象大小内幕浅析

    欢迎支持笔者新作:<深入理解Kafka:核心设计与实践原理>和<RabbitMQ实战指南>,同时欢迎关注笔者的微信公众号:朱小厮的博客. 欢迎跳转到本文的原文链接:https: ...

  9. 使用JOL工具直接查看出java对象大小

    JOL全称为Java Object Layout,是用来分析JVM中对象布局的工具,它可以帮我们在运行时计算某个对象的大小. 引入JOL依赖,如下: <!-- https://mvnreposi ...

最新文章

  1. bat 复制文件夹_怎么生成电脑上文件夹的目录结构
  2. 实现html锚点的两种方式
  3. 专题突破一之分块——Untitled Problem II,Balanced Lineup,[ioi2009]Regions
  4. 机载计算机结构,机载计算机
  5. 2021年世界科技进展100项
  6. java中面向对象_java中的面向对象
  7. C++ 数据结构第二章 ----- 线性表
  8. pcl点云库python实现_如何有效地将ROS PointCloud2转换为pcl点云并在python中将其可视化...
  9. 网易云音乐云盘存歌曲加歌词
  10. 28款超级绿色版杀软,奉献给各位!【迅雷下载】
  11. 【项目简介】LinkWeChat:基于企业微信开源系统
  12. 工业设计与钣金工艺是怎么相互相成的
  13. 设计模式二十四讲之《状态模式》
  14. 全国高中数学联赛——数论
  15. c++语言设计五子棋游戏,C++实现五子棋游戏
  16. Failing because I am unlikely to write too排查方案
  17. 确定十二星座的日期范围
  18. 简单的html图片上传工具
  19. ftp 出现Passive mode refused 解决办法
  20. 栅格数据去除黑边并无缝拼接(envi,arcgis)

热门文章

  1. 合工大计算机考研导师,合肥工业大学计算机与信息学院导师介绍:胡东辉
  2. PKUSC 模拟赛 day1 下午总结
  3. mtk插u盘如何休眠?_iOS13.3.1 U盘越狱卡代码问题,你也是吗?
  4. 太用力的人跑不远(转)
  5. 怎样把视频中的音频提取成mp3?
  6. 前端获取QQ音乐(mp3+m4a)
  7. 2021年危险化学品经营单位主要负责人试题及解析及危险化学品经营单位主要负责人模拟考试题
  8. 虚幻蓝图实现只狼的钩索系统(2)-射线检测
  9. 微型计算机数据处理的基本单位,计算机内部数据处理的基本单位是()。
  10. 用C++ 输出[1,100]范围内的所有奇数,每行10个。