想要查看java对象在运行时的实际占用内存大小。网上大部分方法都是雷同,都是出自
查看java对象所占内存大小-云社区-华为云
这里面的提供的4种方法仅仅适合jdk8及以下版本。
如果项目使用的是dk11、jdk18等高级版本就无法使用,上面帖子中第一种和第二种方法就不能用了,下面给出相应的修复方法。
1、
ObjectSizeCalculator这个类在jdk9以上就不提供了。因此需要单独引入进来,mvn坐标如下:
<dependency>
<groupId>com.xenoamess</groupId>
<artifactId>nashorn</artifactId>
<version>jdk8u265-b01-x3</version>
</dependency>
这时候如果直接调用ObjectSizeCalculator.getObjectSize()方法时,回报如下错误:
Exception in thread "main" java.lang.reflect.InaccessibleObjectException: Unable to make field transient java.lang.Object[] java.util.ArrayList.elementData accessible: module java.base does not "opens java.util" to unnamed module @59690aa4
at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:354)
at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:297)
at java.base/java.lang.reflect.Field.checkCanSetAccessible(Field.java:180)
at java.base/java.lang.reflect.Field.setAccessible(Field.java:174)
at org.apache.lucene.util.RamUsageEstimator.createCacheEntry(RamUsageEstimator.java:497)
at org.apache.lucene.util.RamUsageEstimator.measureObjectSize(RamUsageEstimator.java:455)
at org.apache.lucene.util.RamUsageEstimator.sizeOf(RamUsageEstimator.java:333)
at org.apache.lucene.util.RamUsageEstimator.humanSizeOf(RamUsageEstimator.java:586)
at com.obj.size.ObjSize.main(ObjSize.java:49)
原因就是在jdk9时,对jdk底层的包进行重构优化,引入模块的概念,一些私有方法不能直接反射调用。因此需要增加如下jvm参数:
--add-opens
java.base/java.lang=ALL-UNNAMED
--add-opens
java.base/sun.net.util=ALL-UNNAMED
--add-opens
java.base/java.util=ALL-UNNAMED
--add-opens
java.base/java.lang.reflect=ALL-UNNAMED
idea添加方法
添加之后,代码执行时不会报错。
2、
通过三方工具类RamUsageEstimator.sizeOf(map)调用时,依然会报错,错误的修复方式见上面。
3、
通过 ClassLayout.parseInstance(Integer.valueOf(122)).toPrintable()方法只能得到对象的内存布局和对象的大小(只能看到自己本身),它所引用的对象实例大小是不会计算在里面的。如果要计算当前对象和对象引用的所有对象实例可以使用1和2中的方法。
参考:
对象大小_在 Java 中,确定对象大小的最佳方法是啥?_IT常识