如何计算一个对象的大小

 JDK版本1.8

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

堆内存占用大小的工具类:RamUsageEstimator

//计算指定对象及其引用树上的所有对象的综合大小,单位字节

long RamUsageEstimator.sizeOf(Object obj)

//计算指定对象本身在堆空间的大小,单位字节

long RamUsageEstimator.shallowSizeOf(Object obj)

//计算指定对象及其引用树上的所有对象的综合大小,返回可读的结果,如:2KB

String RamUsageEstimator.humanSizeOf(Object obj)

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

package com.test;

import jdk.nashorn.internal.ir.debug.ObjectSizeCalculator;
import org.apache.lucene.util.RamUsageEstimator;

import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Test7 {

    public static void main(String[] args) {
        String s = "";
        for (int i = 0; i < 20480; i++) {
            s += "0";
        }
        System.out.println("实际大小:" + s.getBytes(StandardCharsets.UTF_8).length + " byte");
        System.out.println("占用内存:" + RamUsageEstimator.sizeOf(s) + " byte");
        System.out.println("占用内存:" + RamUsageEstimator.sizeOfObject(s) + " byte");
        System.out.println("占用内存:" + ObjectSizeCalculator.getObjectSize(s) + " byte");//JDK自带工具
        System.out.println();
        Map<Object, Object> map = new HashMap<>();
        for (int i = 0; i < 1024; i++) {
            map.put(i, "0");
        }
        List<Object> list = new ArrayList<>();
        map.put("list", list);
        System.out.println("map占用内存:" + RamUsageEstimator.sizeOfMap(map) + " byte");
        System.out.println("map占用内存:" + RamUsageEstimator.sizeOfObject(map) + " byte");
        System.out.println("map占用内存:" + ObjectSizeCalculator.getObjectSize(map) + " byte");//JDK自带工具
        System.out.println();
        for (int i = 0; i < 1024; i++) {
            list.add(0);
        }
        System.out.println("list占用内存:" + RamUsageEstimator.sizeOfCollection(list) + " byte");
        System.out.println("map占用内存:" + RamUsageEstimator.sizeOfMap(map) + " byte");
        System.out.println("map占用内存:" + RamUsageEstimator.sizeOfObject(map) + " byte");
        System.out.println("map占用内存:" + ObjectSizeCalculator.getObjectSize(map) + " byte");//JDK自带工具
        System.out.println();

        Stu stu = new Stu();
        System.out.println("stu占用内存:" + RamUsageEstimator.sizeOfObject(stu) + " byte");
        System.out.println("stu占用内存:" + ObjectSizeCalculator.getObjectSize(stu) + " byte");//JDK自带工具
        System.out.println();
        stu.setList(list);
        System.out.println("stu占用内存:" + RamUsageEstimator.sizeOfObject(stu) + " byte");
        System.out.println("stu占用内存:" + ObjectSizeCalculator.getObjectSize(stu) + " byte");//JDK自带工具
        System.out.println();
        stu.setMap(map);
        System.out.println("stu占用内存:" + RamUsageEstimator.sizeOfObject(stu) + " byte");
        System.out.println("stu占用内存:" + ObjectSizeCalculator.getObjectSize(stu) + " byte");//JDK自带工具
        System.out.println();
    }

    static class Stu {
        private String name;
        private List<Object> list;
        private Map<Object, Object> map;

        public void setName(String name) {
            this.name = name;
        }

        public void setList(List<Object> list) {
            this.list = list;
        }

        public void setMap(Map<Object, Object> map) {
            this.map = map;
        }
    }
}
实际大小:20480 byte
占用内存:41000 byte
占用内存:41000 byte
占用内存:41000 byte

map占用内存:344232 byte
map占用内存:344216 byte
map占用内存:57592 byte

list占用内存:266280 byte
map占用内存:610472 byte
map占用内存:344216 byte
map占用内存:62528 byte

stu占用内存:256 byte
stu占用内存:24 byte

stu占用内存:256 byte
stu占用内存:5016 byte

stu占用内存:256 byte
stu占用内存:62552 byte

测试了,发现还是JDK自带的这个好用。ObjectSizeCalculator.getObjectSize

 System.out.println("stu占用内存:" + ObjectSizeCalculator.getObjectSize(stu) + " byte");//JDK自带工具

 

————————————————

Java基本类型长度及对应对象的字节长度

基本类型长度the size of an object
Int416
Short216
Long824
Byte116
Character116
Float416
Double824

java对象在内存中的结构

对象头(Mark Word)用于存储对象自身的运行时数据, 如哈希码(HashCode)、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等等
Class对象指针:Class对象指针的大小也是4个字节,其指向的位置是对象对应的Class对象(其对应的元数据对象)的内存地址
对象实际数据:这里面包括了对象的所有成员变量,其大小由各个成员变量的大小决定,比如:byte和boolean是1个字节,short和char是2个字节,int和float是4个字节,long和double是8个字节,reference是4个字节
对齐:最后一部分是对齐填充的字节,按8个字节填充
Java Integer对象的内存结构

 

Java Array对象的内存结构

 

注意:数组对象和其他对象稍有不同,因为数据有一个长度length字段,所以在对象头后面还多了一个int类型的length字段,占4个字节,接下来才是数组中的数据
————————————————
版权声明:本文为CSDN博主「笃志近思」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/wuwenxiang91322/article/details/80216420

 

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值