加入收藏 | 设为首页 | 会员中心 | 我要投稿 衡阳站长网 (https://www.0734zz.cn/)- 数据集成、设备管理、备份、数据加密、智能搜索!
当前位置: 首页 > 综合聚焦 > 资源网站 > 资源 > 正文

怎样计算一个 Java 对象大小?这儿有几种方法

发布时间:2020-03-28 00:56:27 所属栏目:资源 来源:站长网
导读:在计算机发展的早期阶段,硬件的发展速度慢,容量小,所以 软件开发 人员写起代码里对 byte、bit 都是「斤斤计较」,这才使用写出来的应用能在我们今天看起来那么小的,配置那么低的硬件中运行良好,同时效果惊人。 那么计算机发展到今天,硬件看似配置越
  在计算机发展的早期阶段,硬件的发展速度慢,容量小,所以软件开发人员写起代码里对 byte、bit 都是「斤斤计较」,这才使用写出来的应用能在我们今天看起来那么小的,配置那么低的硬件中运行良好,同时效果惊人。  那么计算机发展到今天,硬件看似配置越来越高,但依然架不住你随意写,搞不好应用就挂了。另外像游戏等一些行业还是「锱铢必较」,让应用能 稳定的运行。在Java 应用里,要想精确计算,需要对于对象的占用大小做到心里有数。那这篇文章一起来看看, 在 Java 的世界里,一个对象的大小究竟是多少呢?有哪些方式能够计算对象大小。  要看一个对象的大小,首先需要看Java 运行的平台是 32位还是 64位的 ,其次还要看对象内有多少属性(field)。最后还有一些 JVM 自身需要 在对象里记录的信息,比如说有GC的状态、同步状态、数组长度等等多种信息。这些项汇总求和,基本就是一个对象的大小了。不过VM为了效率,会采用固定长度,比如 8 位的整数倍来统一存储。这种情况下,如果原对象大小不足时,就会扩展对齐来存储。  好的,下面来看下 JVM 里,一个Java 对象大小占用多少。  由于现在基本操作系统基本都是64位,咱们后面都以64位 JVM 来说明。  首先来看两个例子:    例子1里, App 这个对象占用内存大小是多少 byte 呢?答案是 16。例子2 又是多少呢?答案是 24。  这里是怎么计算的呢?  计算方式  和开头的文字描述类似,在Java 里一个对象大小,是由这些内容组成  一个对象Object 大小 = Header + Primitive Fields + Reference Fields + Alignment & Padding`  其中的 Header 部分,就是 JVM 用于记录特定信息的,一版也叫做 object header,在 OpenJDK 的汇总页里,描述是这样的:  Common structure at the beginning of every GC-managed heap object. (Every oop points to an object header.) Includes fundamental information about the heap object's layout, type, GC state, synchronization state, and identity hash code. Consists of two words. In arrays it is immediately followed by a length field. Note that both Java objects and VM-internal objects have a common object header format.  我们看到 object header 由这些部分组成:  mark word  klass pointer  (Optinal) 如果是数组,会记录数组的长度  mark word  The first word of every object header. Usually a set of bitfields including synchronization state and identity hash code. May also be a pointer (with characteristic low bit encoding) to synchronization related information. During GC, may contain GC state bits.  klass pointer  The second word of every object header. Points to another object (a metaobject) which describes the layout and behavior of the original object. For Java objects, the "klass" contains a C++ style "vtable".  总结一下,对象头里,基本是 GC的状态、同步状态、identity hash code,数组长度,以及 class 元信息的指针。  header 的长度由两个 word 组成。mark word 在 64位VM里,长度是 8 bytes。klass pointer 的长度64位VM下受参数-XX:+UseCompressedOops配置控制, 可能是 4 bytes,也可能是8 bytes。  例子1,我们看关闭情况-XX:-UseCompressedOops  16 bytes 全都是对象头。  如果打开,则 object header 占 12 个bytes, 另外4个会补齐。  例子2,输出是这样:  增加了 field 的占用, 这里的占用大小,就是咱们常说的 基本数据类型 的大小。如果有对象引用类型,就再加上这些的大小即可。  工具  下面的这些工具及方式,可用来计算对象的大小。  1.JOL  JOL 是 OpenJDK 提供的一个工具,在项目中添加依赖后可直接使用。  然后代码里直接输出即可。  2.Instrument  在 Instrument 包的 Instrumentation类内,有一个可以直接获取对象大小的方法,注释如下:  那怎样拿到 Instrument,从而调用这个方法,一般是通过 Agent attach 到 VM上来得到,一种是Agent 实现premain方法,一种是agentMain方法,区别在于attach的时机。  比如你自己定义了一个Agent 的 jar  后面咱们在代码里直接静态调用 getObjectSize 方法就行了。  3.SA  我之前的文章(Java虚拟机的显微镜 Serviceability Agent)里介绍过 SA(Serviceablity Agent), 通过 SA,可以做到许多剖析 JVM 的事情。观察对象的组成和大小当然也不在话下。  通过SA来观察上面例子2,效果是这样的:怎样计算一个 Java 对象大小?这儿有几种方法  咱们能看到,整个对象先是_mark(mark word), 之后是 compressed klass(klass pointer ), 再后面是实例包含的属性。 如果红框所示,在 klass pointer 里面包含一个 _layout_helper,显示的就是该对象的大小。  此外,在SA里的 Console 里,可以像命令行一样交互,也可以显示对象的大小。  PS: 对于对象的大小,JVM在初始化分配的时候,会对 field 有个「重排序」,给 field 的分配排序,从而节省空间。比如先分配byte 或者 boolean 之后,再分配 int 这些,那 byte 之后可能需要增加 3 bytes 进行 padding,重排序可以减小空间占用。  比如有这些属性:    在输出对象内容,我们发现,并不是按属性的声明顺序来分配的,这样只占用24 bytes,如果按声明顺序,那应该先分配byte, 之后再分配 int 这样为了对齐,会额外增加 3 个 bytes的(alignment/padding gap)最后可能会占用到32bytes。  为了减少空间浪费,一般情况下,field分配的优先依次顺序是:  double > long > int > float > char > short > byte > boolean > object reference。  这里有个基本的原则是:尽可能先分配占用空间大的类型。

(编辑:衡阳站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读