写点什么

[Java] 计算 Java 对象大小

  • 2025-01-10
    福建
  • 本文字数:1678 字

    阅读完需:约 6 分钟


  • 在 Java 应用程序的性能优化场景中,时常需要考虑 Java 对象的大小,以便观测、评估后,进一步提出优化方案:


  • 占用内存的大小。(比如 本地内存)

  • 对象数据在网络传输中占用的网络带宽

  • 对象数据在存储时占用的磁盘空间

  • ...


概述


对象大小如何计算


  • 对象大小包括俩部分的内容,对象头和对象内容:



对象头


此处假设是 64 位的 JVM


  • 对象地址,占 4 个字节。

  • 对象标记,占 8 个字节,包括锁标记,hashcode, age 等。

  • 数组长度标记,占 4 个字节。如果对象是一个数组,会有此标记,否则没有。


对象内容


  • 对象内部属性。如果属性是对象的话,那么记录的是对象的地址,占用 4 个字节。


8 字节对齐


  • Java对象采用的是 8 字节对齐。对象大小必须是8的倍数,不足需要补齐。


比如,计算一个对象只需要 20 字节,那么实际占用 24 字节。


计算对象大小的方法


  • 方法 1 和方法 2,在 String 对象的计算上,存在差异;Integer 和 Map 的计算,经简单检验:不存在差异。


方法 1:基于 JDK 原生库 【推荐】


import jdk.nashorn.internal.ir.debug.ObjectSizeCalculator;import lombok.extern.slf4j.Slf4j;
@Slf4jpublic class ObjectCalculatorTest { public static void main(String[] args) { String text = "Hello World!"; //12 chars Long objectSizeBytes = ObjectSizeCalculator.getObjectSize(text); log.info("objectSizeBytes: {} bytes", objectSizeBytes );//64 bytes
Integer number = new Integer(11); objectSizeBytes = ObjectSizeCalculator.getObjectSize(number); log.info("objectSizeBytes: {} bytes", objectSizeBytes );//16 bytes
Map<String, String> map = new HashMap<>(); objectSizeBytes = ObjectSizeCalculator.getObjectSize(number); log.info("objectSizeBytes: {} bytes", objectSizeBytes );//48 bytes }}
复制代码


方法 2:基于lucene-core


  • 引入依赖


<dependency>	<groupId>org.apache.lucene</groupId>	<artifactId>lucene-core</artifactId>	<version>8.7.0</version></dependency>
复制代码


  • 计算对象大小


jdk 1.8

import lombok.extern.slf4j.Slf4j;import org.apache.lucene.util.RamUsageEstimator;
@Slf4jpublic class ObjectCalculatorTest { public static void main(String[] args) { String text = "Hello World!"; //12 char = 12 byte objectSizeBytes = RamUsageEstimator.shallowSizeOf( text ); log.info("objectSizeBytes: {} bytes", objectSizeBytes );//24 bytes Integer number = new Integer(11); System.out.println(RamUsageEstimator.shallowSizeOf(number));//16 bytes
Map<String, String> map = new HashMap<>(); System.out.println(RamUsageEstimator.shallowSizeOf(map));//48 bytes }}
复制代码


案例分析(基于lucene-core库)


Integer 对象大小分析


  • 它是对象,占用 4 个字节

  • 对象标记,占用 8 个字节

  • 查看源码,发现:


Integr 内容只有以下一个非 static 的属性,是一个int的基本类型属性,占用4个字节.static 修饰的方法属性都是存储在方法区的,不占用对象空间。


    /**     * The value of the {@code Integer}.     *     * @serial     */    private final int value;
复制代码


故 total = 4 + 8 + 4 = 16


HashMap 对象大小分析


  • 它是对象,占用 4 个字节

  • 对象标记,占用 8 个字节

  • 查看源码,发现:


HashMap 是继承了 AbstractMap 的,AbstractMap 中有以下的俩个属性,一共占用 8 个字节。因为只是存储了 keySet, values 的地址


transient Set<K>        keySet;transient Collection<V> values;
复制代码


  • HashMap 中有以下属性,共占用 6 * 4 = 24 个字节。


transient Node<K,V>[] table;transient Set<Map.Entry<K,V>> entrySet;transient int size;transient int modCount;int threshold;final float loadFactor;
复制代码


total = 4 + 8 + 8 + 24 = 44, 由于 java 是 8 字节对齐的,故一共是 48 字节。


文章转载自:千千寰宇

原文链接:https://www.cnblogs.com/johnnyzen/p/18662883

体验地址:http://www.jnpfsoft.com/?from=001YH

用户头像

还未添加个人签名 2023-06-19 加入

还未添加个人简介

评论

发布
暂无评论
[Java] 计算Java对象大小_Java_不在线第一只蜗牛_InfoQ写作社区