Java中计算对象的大小

一、计算对象大小的方法

Java中如何计算对象的大小呢,找到了4种方法:

1.java.lang.instrument.Instrumentation的getObjectSize方法;

2.BTraceUtils的sizeof方法;

3.http://yueyemaitian.iteye.com/blog/2033046中提供的代码计算;

4.https://github.com/mingbozhang/memory-measurer提供的工具包;

本质上java.lang.instrument.Instrumentation的使用是其他三种方法的基础,但是该类中的方法getObjectSize只是计算了对象本身,JDK注释描述:

Returns an implementation-specific approximation of the amount of storage consumed by
the specified object. The result may include some or all of the object's overhead,
and thus is useful for comparison within an implementation but not between implementations.

第2种是使用BTrace的方法,可以对生产环境的程序进行检测,但是BTraceUtils的sizeof实现上直接调用的还是java.lang.instrument.Instrumentation的getObjectSize方法,所以还是存在第1种方法的问题。第3中方法可以计算数组的大小,但是无法计算HashMap等对象。第4种方法支持对HashMap等常见对象的大小计算。

第1种方法网上可以找到很多资料可以参考,第3中方法链接博文内容已经很详细。这里给出第2中方法以及第4种方法的使用步骤。

二、BTrace中计算对象大小

我使用的BTrace是Java VisualVM中的插件版。VisualVM打开方式为命令行输入jvisualvm,

Java中计算对象的大小

安装插件BTrace,安装成功的话,查看Plugin窗口

Java中计算对象的大小

安装插件这部分工作这里就不说了,下面演示如何使用。

启动tomcat,在VisualVM左侧中选择刚刚启动的tomcat,右键弹框中选择Trace application

Java中计算对象的大小

这时右侧将会打开BTrace窗口:

Java中计算对象的大小

上面右侧代码是BTrace用于检测com.test.data.TestBtrace类在执行search方法后返回值的大小。

import com.sun.btrace.annotations.*;
import static com.sun.btrace.BTraceUtils.*; @BTrace public class Sizeof {
@OnMethod(
clazz="com.test.data.TestBtrace",
method = "search", location = @Location(Kind.RETURN)
)
public static void onnew(@Return Object obj) {
println(Strings.concat("object of: ", Reflective.name(Reflective.classOf(obj))));
println(Strings.concat("size: ", Strings.str(sizeof(obj))));
}
}

点击start按钮执行成功显示如下(红框内),说明已经进入监视状态:

Java中计算对象的大小

执行tomcat上面的com.test.data.TestBtrace中search方法,BTrace控制台打印出了返回结果对象的类型以及对象大小,每次都是48 bytes。

Java中计算对象的大小

具体BTrace脚本说明以及例子可以参考:https://github.com/mingbozhang/btrace

其中docs有帮助文档,samples有例子。

三、使用MemoryMeasurer计算对象大小

到https://github.com/mingbozhang/memory-measurer上面将源码下载到本地,编译需要本地预先安装java,maven。

1.加入检测代码到目标代码中

这里的使用方法不像BTrace的低侵入,需要在代码中加入检测代码:

long memory = MemoryMeasurer.measureBytes(objectToTest);

通过输出日志或者其他方式将上面代码中变量memory内容获取到。

2.启动TOMCAT是在JAVA_OPTS中加入:

-javaagent:<实际目录>/memory-measurer-0.1.0-SNAPSHOT.jar

3.启动TOMCAT,操作application并查看打印出的待检测对象的大小信息。

使用该方法测试出的com.test.data.TestBtrace中search方法返回结果对象大小为:349264 bytes

注意:由于此项目依赖guava包,如果待测试代码直接main方法启动使用target生成的memory-measurer-0.1.0-SNAPSHOT.jar,如果是检测tomcat上的application则需要使用target生成的memory-measurer-0.1.0-SNAPSHOT-jar-with-dependencies.jar。

四、思考

找到的这几种方法第1、2中是比较官方一些的方法。3、4是个人写的代码或者工具。如果寻找容器对象真实大小这个需求是个迫切需求,为什么没有看到官方版本的对象真实大小计算工具?

上一篇:【Redis笔记(四)】 Redis数据结构 - list链表


下一篇:【Java基础】Java中new对象的过程