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,

安装插件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中计算对象的大小的更多相关文章
- JAVA中JavaBean对象之间属性拷贝的方法
JAVA中JavaBean对象之间的拷贝通常是用get/set方法,但如果你有两个属性相同的JavaBean或有大部分属性相同的JavaBean,对于这种情况,可以采用以下几个简便方法处理. 下面对这 ...
- 浅谈Java中的对象和引用
浅谈Java中的对象和对象引用 在Java中,有一组名词经常一起出现,它们就是“对象和对象引用”,很多朋友在初学Java的时候可能经常会混淆这2个概念,觉得它们是一回事,事实上则不然.今天我们就来一起 ...
- 【译】Java中的对象序列化
前言 好久没翻译simple java了,睡前来一篇. 译文链接: http://www.programcreek.com/2014/01/java-serialization/ 什么是对象序列化 在 ...
- java中直接打印对象
java中直接打印对象,会调用对象.toString()方法.如果没有重写toString()方法会输出"类名+@+hasCode"值,hasCode是一个十六进制数 //没有重写 ...
- 如何使用java中的对象
使用java中的对象,分2步: 1.创建一个对象: 2.使用对象的属性和方法. 见下面的示例代码: package com.imooc; //1.定义一个类 public class Telphone ...
- Java中String对象的不可变性
首先看一个程序 package reverse; public class Reverse { public static void main(String[] args) { String c1=n ...
- JAVA中JavaBean对象之间拷贝的方法
JAVA中JavaBean对象之间的拷贝通常是用get/set方法,但如果你有两个属性相同的JavaBean或有大部分属性相同的JavaBean,有个更简便的方法,他们之间的拷贝可以通过copyPro ...
- Java中的对象池技术
java中的对象池技术,是为了方便快捷地创建某些对象而出现的,当需要一个对象时,就可以从池中取一个出来(如果池中没有则创建一个),则在需要重复重复创建相等变量时节省了很多时间.对象池其实也就是一个内存 ...
- 【学习笔记】Java中生成对象的5中方法
概述:本文介绍以下java五种创建对象的方式: 1.用new语句创建对象,这是最常用的创建对象的方式. 2.使用Class类的newInstance方法 3.运用反射手段,调用java.lang.re ...
随机推荐
- Linux 设备驱动之 UIO 机制
一个设备驱动的主要任务有两个: 1. 存取设备的内存 2. 处理设备产生的中断 对于第一个任务.UIO 核心实现了mmap()能够处理物理内存(physical memory),逻辑内存(logica ...
- LeetCode第[54]题(Java):Spiral Matrix
题目:螺旋矩阵 难度:Medium 题目内容: Given a matrix of m x n elements (m rows, n columns), return all elements of ...
- Redis分区探究
Redis比较好的分区算法是采用Hash分区算法 也就是我们可以将所有的server例如:user1,user2,user3.通过hash函数将key转化为一个数字然后求余找到需要存储的server. ...
- os.path.abs()与os.path.realpath()的一点区别
相同点 1. 两者都是返回绝对路径,如果参数path为空,则返回当前文件所在目录的绝对路径 当前py文件所在的目录是revise print(os.path.abspath("") ...
- 三十四 Python分布式爬虫打造搜索引擎Scrapy精讲—scrapy信号详解
信号一般使用信号分发器dispatcher.connect(),来设置信号,和信号触发函数,当捕获到信号时执行一个函数 dispatcher.connect()信号分发器,第一个参数信号触发函数,第二 ...
- uva 1511 最小生成树
https://vjudge.net/problem/UVA-1151 题意,给出N个点以及二维坐标,可以在任意两点间建立通路,代价是两点欧几里得距离的平方,同时有q个套餐,套餐x有qx个点,代价是q ...
- Vue学习手札
HTML 特性是不区分大小写的.所以,当使用的不是字符串模板,camelCased (驼峰式) 命名的 prop 需要转换为相对应的 kebab-case (短横线隔开式) 命名: Vue.compo ...
- java继承的一些问题
如果在父类中,你声明了一个静态变量. 然后你有两个子类继承了这个父类.我们想看看这两个子类调用继承的父类的类变量a是不是同一个值. 这时候注意,我们在子类的时候不能重写static int a = a ...
- VS10x CodeMap
VS10x CodeMap 注册码(key): #$aCN/L/ra73OaqCJENXc2JIDL61IMawNWBBX+PxhBzobE9w3QlcrwoXeB3DWBC2f56y9r0Hx2XP ...
- HTTPPost/AFNetWorking/JSONModel/NSPredicate
一.HTTPPost================================================ 1. POST方式发送请求 HTTP协议下默认数据发送请求方法是GET方式,若需要 ...