一、计算对象大小的方法

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,

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

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

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

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

上面右侧代码是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按钮执行成功显示如下(红框内),说明已经进入监视状态:

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

具体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是个人写的代码或者工具。如果寻找容器对象真实大小这个需求是个迫切需求,为什么没有看到官方版本的对象真实大小计算工具?

Java中计算对象的大小的更多相关文章

  1. JAVA中JavaBean对象之间属性拷贝的方法

    JAVA中JavaBean对象之间的拷贝通常是用get/set方法,但如果你有两个属性相同的JavaBean或有大部分属性相同的JavaBean,对于这种情况,可以采用以下几个简便方法处理. 下面对这 ...

  2. 浅谈Java中的对象和引用

    浅谈Java中的对象和对象引用 在Java中,有一组名词经常一起出现,它们就是“对象和对象引用”,很多朋友在初学Java的时候可能经常会混淆这2个概念,觉得它们是一回事,事实上则不然.今天我们就来一起 ...

  3. 【译】Java中的对象序列化

    前言 好久没翻译simple java了,睡前来一篇. 译文链接: http://www.programcreek.com/2014/01/java-serialization/ 什么是对象序列化 在 ...

  4. java中直接打印对象

    java中直接打印对象,会调用对象.toString()方法.如果没有重写toString()方法会输出"类名+@+hasCode"值,hasCode是一个十六进制数 //没有重写 ...

  5. 如何使用java中的对象

    使用java中的对象,分2步: 1.创建一个对象: 2.使用对象的属性和方法. 见下面的示例代码: package com.imooc; //1.定义一个类 public class Telphone ...

  6. Java中String对象的不可变性

    首先看一个程序 package reverse; public class Reverse { public static void main(String[] args) { String c1=n ...

  7. JAVA中JavaBean对象之间拷贝的方法

    JAVA中JavaBean对象之间的拷贝通常是用get/set方法,但如果你有两个属性相同的JavaBean或有大部分属性相同的JavaBean,有个更简便的方法,他们之间的拷贝可以通过copyPro ...

  8. Java中的对象池技术

    java中的对象池技术,是为了方便快捷地创建某些对象而出现的,当需要一个对象时,就可以从池中取一个出来(如果池中没有则创建一个),则在需要重复重复创建相等变量时节省了很多时间.对象池其实也就是一个内存 ...

  9. 【学习笔记】Java中生成对象的5中方法

    概述:本文介绍以下java五种创建对象的方式: 1.用new语句创建对象,这是最常用的创建对象的方式. 2.使用Class类的newInstance方法 3.运用反射手段,调用java.lang.re ...

随机推荐

  1. scala学习手记34 - trait方法的延迟绑定

    trait的方法的延迟绑定就是先混入的trait的方法会后调用.这一点从上一节的实例中也可以看出来. 下面再来看一个类似的例子: abstract class Writer { def write(m ...

  2. spring的AOP动态代理--JDK代理和CGLIB代理区分以及注意事项

    大家都知道AOP使用了代理模式,本文主要介绍两个代理模式怎么设置以及区别,对原文一些内容进行了引用后加入了自己的理解和更深入的阐述:   一.JDK代理和CGLIB代理的底层实现区别* JDK代理只能 ...

  3. Java 基于JavaMail的邮件发送

    http://blog.csdn.net/xietansheng/article/details/51673073 http://blog.csdn.net/xietansheng/article/d ...

  4. 火车头采集器db3导出sql语句

    1.通过火狐 sqlite mananger工具,将.db3文件,导出为.sql文件2.右击表面content,属性:Export table 3.不要勾选 include create table. ...

  5. H5测试

    H5是什么? H5的全称是HTML5,其实就是:移动端WEB页面. H5与原生 APP的区别: APP是使用原生系统内核的,相当于直接在系统上操作,是我们传统意义上的软件,更加稳定. H5的APP先得 ...

  6. python之单元测试框架—unittest(补充)

    一. unittest最核心的四个概念 unittest中最核心的四个概念是:test case,test suite,test runner,test fixture TestCase:一个test ...

  7. SimpleDateFormat函数语法

    SimpleDateFormat函数语法:         G 年代标志符         y 年         M 月         d 日         h 时 在上午或下午 (1~12)  ...

  8. 【lightoj-1025】The Specials Menu(区间DP)

    题目链接:http://www.lightoj.com/volume_showproblem.php?problem=1025 [题目大意] 求一个字符串删去任意字符可以构成多少个不同的回文串 [分析 ...

  9. Node net模块与http模块一些研究

    这周遇到一个有意思的需求,端上同学希望通过 socket 传送表单数据(包含文件内容)到 node 端,根据表单里的文件名.手机号等信息将文件数据保存下来.于是我这样写了一下--socket_serv ...

  10. [置顶] 关于Android实现 退出登录那些小事?

    使用场景: 相信大家应该清楚每一个app都会有一个"退出登陆"的功能,有的可能在个人中心有的在设置里面.当用户点击退出之后需要将所有的Activity都finish掉,开始是想将栈 ...