当前位置: 首页 > 科技观察

如何获取一个对象的真实内存大小

时间:2023-03-17 16:19:28 科技观察

如何获取一个对象的真实内存大小介绍一个工具(memory-measurer)可以很方便的测量一个对象的真实内存大小如果有这样一个User对象publicclassUser{privateIntegerid;privateStringmobile;privateDatecreateTime;}先看一个空的User对象的内存占用Useru=newUser();System.out.println(MemoryMeasurer.measureBytes(u));//24System.out.println(ObjectGraphMeasurer.measure(u));//Footprint{Objects=1,References=3,Primitives=[]},我们可以知道一个对象的三个引用一共占用24个字节,一个一个赋值后占用多少内存?//分配idIntegerid=newInteger(1);System.out.println(MemoryMeasurer.measureBytes(id));//16u.setId(id);System.out.println(MemoryMeasurer.measureBytes(u));//40System.out.println(ObjectGraphMeasurer.measure(u));//Footprint{Objects=2,References=3,Primitives=[int]}一个Integer对象占用16个字节,所以给id赋值后,用户对象变为24+16=40字节。//给mobile赋值Stringmobile="13600000001";System.out.println(MemoryMeasurer.measureBytes(mobile));//64u.setMobile(mobile);System.out.println(MemoryMeasurer.measureBytes(u));//104System.out.println(ObjectGraphMeasurer.measure(u));//Footprint{Objects=4,References=4,Primitives=[intx2,charx11]}一个11位长的移动字符串对象占64字节,所以用户对象变成40+64=104字节//给createTime赋值DatecreateTime=newDate();System.out.println(MemoryMeasurer.measureBytes(createTime));//24字节u.setCreateTime(createTime);System.out.println(MemoryMeasurer.measureBytes(u));//128System.out.println(ObjectGraphMeasurer.measure(u));//Footprint{Objects=5,References=5,Primitives=[intx2,long,charx11]}可以看出一个Date对象占用24字节,所以一个属性不为空的User对象占用128字节内存。此外,您还可以使用另一个工具——JOL(JavaObjectLayout)——来了解更详细的Footprint信息。通过上面的工具,我们只知道一个空的User对象占用24个字节,一个简单的Footprint{Objects=1,References=3,Primitives=[]}通过这个工具,我们可以知道这24个字节是怎么分配的System.out.println(ClassLayout.parseClass(User.class).toPrintable());memorymeasurer.Userobjectinternals:OFFSETSIZETYPEDESCRIPTIONVALUE012(objectheader)N/A124IntegerUser.idN/A164StringUser.mobileN/A204DateUser.createTimeN/AInstancesize:24bytesSpacelosses:0bytesinternal+0bytesexternal=0bytestotal以上知道一个Integer对象占16个字节,看看这16个字节是怎么分配的valueN/AInstancesize:16bytesSpacelosses:0bytesinternal+0bytesexternal=0bytestotal上面我们知道一个11位长的String对象占64位,看看字节是怎么分配的System.out.println(ClassLayout.parseClass(String.class).toPrintable());java.lang.Stringobjectinternals:OFFSETSIZETYPEDESCRIPTIONVALUE012(objectheader)N/A124char[]String.valueN/A164intString.hashN/A204(lossduetothenextobjectalignment)Instancesize:24bytesSpacelosses:0bytesinternal+4bytesexternal=4bytestotal即一个空String对象占用24个字节System.out.println(ClassLayout.parseClass(char[].class).toPrintable());[Cobjectinternals:OFFSETSIZETYPEDESCRIPTIONVALUE016(objectheader)N/A160char[C.N/AInstancesize:16bytesSpacelosses:0bytesinternal+0bytesexternal=0bytestotal长度为0的char数组占用16字节,所以11位长的char数组占用字节:16+2*11=38因为需要8字节对齐,所以要加2字节的填充符,所以变成40字节所以一个11位长的字符串占用24+40=64字节来补充memory-measurer如何使用gitclonehttps://github.com/msteindorfer/memory-measurercdmemory-measurermvncleaninstallpom文件添加依赖com。github.msteindorfermemory-measurer0.1.0-SNAPSHOT运行时显式添加vm参数如-javaagent:/Users/zhugw/workspace/memory-measurer/target/memory-measurer-0.1.0-SNAPSHOT.jarjol说明只需要添加依赖org.openjdk.joljol-core0.6相关参考文档https://github.com/msteindorf...http://openjdk.java.net/proje...http://blog.omalley.id.au/201...