一、计算对象大小的方法

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. Hypernetes简介——真正多租户的Kubernetes Distro

    http://www.dockone.io/article/838 Hypernetes是一个真正多租户的Kubernetes Distro. Hypernetes在Kubernetes基础上增加了多 ...

  2. HTTP Status 500 - javax.el.PropertyNotFoundException: Property 'lkmId' not found on type cn.itcast.entity.LinkMan

    报错 type Exception report message javax.el.PropertyNotFoundException: Property 'lkmId' not found on t ...

  3. charles抓包工具的使用:手机抓包设置和安装证书

    一. 设置手机抓包 第一步:在charles里设置允许手机联网的权限,并设置接入接口 在Charles的菜单栏上选择"Proxy"->"Proxy Settings ...

  4. 连接mysql报错:error 2003 (hy000):can't connect to mysql server on 'localhost' (10061)

    一.mysql 的bin目录下有个MySQLInstanceConfig.exe,运行就可以进行创建数据库实例,创建实例时也可以生成windows 服务,把服务设置成自动启动就可以了 二.安装在D盘的 ...

  5. 【spark】分区

    RDD是弹性分布式数据集,通常RDD很大,会被分成多个分区,保存在不同节点上. 那么分区有什么好处呢? 分区能减少节点之间的通信开销,正确的分区能大大加快程序的执行速度. 我们看个例子 首先我们要了解 ...

  6. TCPL学习笔记:编写expand(s1, s2),将字符串s1中类似于a-z一类的速记符号在s2中扩充完整。可以处理大小写及字符,以及a-b-c, a-z0-9以及-a-z等多种情况。

    话不多说,看代码: #include <stdio.h> #include <stdlib.h> int main(void) { ] = "a-z0-9hahah- ...

  7. 四则运算生成与校检 Python实现

    GitHub地址 https://github.com/little-petrol/Arithmetic.git 合作者: 郭旭 和 卢明凯 设计实现过程 代码的组织主要分为两个部分: 算法与结构体的 ...

  8. react bootstrap-loader

    1.install npm install bootstrap-loader jquery resolve-url-loader 2.webpack.config.js entry: ['bootst ...

  9. Today is weekend不是应该一定会输出吗

    判断语句 If…else块,请看下面这个例子: <%! int day = 3; %> //声明变量感叹号 <html> <head><title>IF ...

  10. 2017.11.17 Demo-stm8+temperature timeing control

    1Find the lab and add in project. Downtown  it from ST  official website..compile it to ensure it pa ...