如何查看一个对象的方法不占用内存当前占用的内存大小

如何获取一个对象所占用的内存空间
[问题点数:20分,结帖人dangdang2471]
如何获取一个对象所占用的内存空间
[问题点数:20分,结帖人dangdang2471]
不显示删除回复
显示所有回复
显示星级回复
显示得分回复
只显示楼主
本帖子已过去太久远了,不再提供回复功能。J2SE(55)
1 对象内存大小度量
原文:http://www.liaohuqiu.net/cn/posts/caculate-object-size-in-java/补充了文中的细节,做了一些订正,加粗斜体是补充和订正
在做内存优化时,需要知道每个对象占用的内存的大小,
一个实例化的对象在内存中需要存储的信息包括:
<span style="color:#.&&&&&&&&&&&对象的头部(对象的GC信息,hash&#20540;,类定义引用等)
<span style="color:#.&&&&&&&&&&&对象的成员变量:包括基本数据类型和引用。如成员变量是一个引用,引用了其他对象,被引用的对象内存另外计算。
如下一个简单的类的定义:
class MyClass {
1.1 实例化一个对象
MyClass myClass = new MyClass();
对象大小分为:
1.1.1自身的大小(Shadow heap size):
直接计算当前对象占用空间大小,包括当前类及超类的基本类型实例字段大小、引用类型实例字段引用大小、实例基本类型数组总占用空间、实例引用类型数组引用本身占用空间大小
1.1.2所引用的对象的大小(Retained heap size):
myClass实例创建出来之后,在内存中所占的大小就是myClass自身大小(Shadow
heap size)。包括类的头部大小以及一个int的大小和一个引用的大小。
myClass&中object&成员变量是一个对象引用,这个被引用的对象也占一定大小。myClass实例所维护的引用的对象所占的大小,称为myClass实例的Retained
heap size。
本文讨论的是对象自身的大小,即Shadow heap size。Retained heap size递归计算即可得。
对象大小的计算可用java.lang.instrument.Instrumentation&或者
dump内存之后用memory analyzer分析。这是一份示例代码
2.1基本数据类型大小
基本数据类型大小如下:&
size(bits)
<span style="color:#
<span style="color:#
<span style="color:#
<span style="color:#
<span style="color:#
<span style="color:#
<span style="color:#
<span style="color:#
<span style="color:#
<span style="color:#
<span style="color:#
<span style="color:#
<span style="color:#
<span style="color:#
<span style="color:#
<span style="color:#
2.2引用的大小
在<span style="color:#位的JVM上,一个对象引用占用<span style="color:#个字节;在<span style="color:#位上,占用<span style="color:#个字节。通过&java
-d64 -version可确定是否是<span style="color:#位的JVM。
使用<span style="color:#个字节是为了能够管理大于<span style="color:#G的内存,如果你的程序不需要访问大于<span style="color:#G的内存,
可通过-XX:&#43;UseCompressedOops选项,开启指针压缩。从Java 1.6.0_23起,这个选项默认是开的。可通过jinfo
-flag UseCompressedOops &pid&查看。
localhost:~ srain$ jinfo -flag UseCompressedOops 13133
-XX:&#43;UseCompressedOops
2.3对象头部的大小
对象头,结构如下:
&#43;------------------&#43;------------------&#43;------------------&#43;---------------.
|&&& mark word&&&& |&&klass pointer& |& array size (opt) |&& &padding&&&|
&#43;------------------&#43;------------------&#43;-------------------&#43;---------------'
每个对象都有一个mark work头部,以及一个引用,指向类的信息。在<span style="color:#位JVM上,markword
4个字节,整个头部有<span style="color:#字节大小。
array size(opt)在对象为数组的时候启用,<span style="color:#字节(<span style="color:#byte)长度。JVM规定对象头(Object
Header)长度为<span style="color:#个字(word),在<span style="color:#bit JVM中,一个word长度为<span style="color:#byte,<span style="color:#bit
JVM中,长度为<span style="color:#byte
在未开启UseCompressedOops的<span style="color:#位JVM上,对象头有<span style="color:#字节大小。
在开启UseCompressedOops的<span style="color:#位机器上,引用(klass
pointer)成了<span style="color:#字节,一共<span style="color:#字节。按照<span style="color:#位对齐,实际占用<span style="color:#字节。
java在<span style="color:#bit模式下开启指针压缩,比<span style="color:#bit模式下,头部会大<span style="color:#byte(_mark区域变成<span style="color:#byte,_class区域被压缩),如果没有开启指针压缩,头部会大<span style="color:#byte(_mark和_class都会变成<span style="color:#byte),jdk1.6推出参数-XX:&#43;UseCompressedOops,在<span style="color:#G内存一下默认会自动打开这个参数,如下:
&[Nathan@laptop&~]$&java&-Xmx31g&-XX:&#43;PrintFlagsFinal&|grep&Compress&&
&&&&&bool&SpecialStringCompress&&&&&&&=&true&&&&&&&&&&&&{product}&&&&&&&&&&&
&&&&&bool&UseCompressedOops&&&&&&&&&&&=&true&&&&&&&&&&&&{lp64_product}&&&&&&
&&&&&bool&UseCompressedStrings&&&&&&&&=&false&&&&&&&&&&&{product}&&&
[Nathan@laptop&~]$&java&-Xmx32g&-XX:&#43;PrintFlagsFinal&|grep&Compress&&
&&&&&bool&SpecialStringCompress&&&&&&&=&true&&&&&&&&&&&&{product}&&&&&&&&&&&
&&&&&bool&UseCompressedOops&&&&&&&&&&&=&false&&&&&&&&&&&{lp64_product}&&&&&&
&&&&&bool&UseCompressedStrings&&&&&&&&=&false&&&&&&&&&&&{product}&&&
3对象的内存布局
<span style="color:#.&&&&&&&&&&&每个对象的内存占用按<span style="color:#字节对齐
<span style="color:#.&&&&&&&&&&&空对象和类实例成员变量
空对象,指的非inner-class,没有实例属性的类。Object&类或者直接继承Object&没有添加任何实例成员的类,即:new
Object()&。
空对象的不包含任何成员变量,其大小即对象头大小:
o&& 在<span style="color:#位JVM上,占用8字节;
o&& 在开启UseCompressedOops的<span style="color:#位JVM上,<span style="color:#
&#43; 4 = 16;
o&& 订正:在开启UseCompressedOops的<span style="color:#位JVM上,object
header长度为<span style="color:#(mark word: 8, kclass pointer: 4),padding为<span style="color:#,对齐后的长度为<span style="color:#;
o&& 在未开启UseCompressedOops的<span style="color:#位JVM上,<span style="color:#
&#43; 4 = 20; 对齐后为<span style="color:#。
o&& 订正:在未开启UseCompressedOops的<span style="color:#位JVM上,长度16(mark
word:8 ,klass pointer 8)。
<span style="color:#.&&&&&&&&&&&对象实例成员重排序
实例成员变量紧随对象头。每个成员变量都尽量使本身的大小在内存中尽量对齐。
比如int按<span style="color:#位对齐,long按<span style="color:#位对齐。为了内存紧凑,实例成员在内存中的排列和声明的顺序可能不一致,实际会按以下顺序排序:
<span style="color:#.&&doubles andlongs
<span style="color:#.&&ints and floats
<span style="color:#.&&shorts andchars
<span style="color:#.&&booleans andbytes
<span style="color:#.&&references
这样做可尽量节省空间。
classMyClass{
&&& byte a;
&&& int c;
&&& boolean d;
&&& long e;
&&& Object f;&&&&&&&
未重排之前:
&&&& 32 bit & & & & & & & & & & & & & & & & &64bit &#43;UseCompressedOops
[HEADER: 12 bytes]& 8&&&&&&&&&&[HEADER: 12 bytes] 12
[a:&&&&&& 1 byte ]&9 & & & & & & & & & &[a:&&&&&& 1 byte ] 13
[padding: 3 bytes] 12&&&&&&&&&& [padding: 3 bytes] 16
[c:&&&&&& 4 bytes] 16 & & & & & & & & [c:&&&&&& 4 bytes] 20
[d:&&&&&& 1 byte ] 17 & & & & & & & & [d:&&&&&& 1 byte ] 21
[padding: 7 bytes] 24&&&&&&&&&& [padding: 3 bytes] 24
[e:&&&&&& 8 bytes] 32 & & & & & & & [e:&&&&&& 8 bytes] 32
[f:&&&&&& 4 bytes] 36 & & & & & & & [f:&&&&&&4 bytes] 36
[padding: 4 bytes] 40&&&&&&&&&& [padding: 4 bytes] 40
重新排列之后:
&&& 32 bit&&&&&&&&&&&&&&&&&&&&& 64bit &#43;UseCompressedOops
[HEADER:& 8 bytes]&8&&&&&&&&&& [HEADER: 12 bytes] 12
[e:&&&&&& 8 bytes] 16&&&&&&&&&& [e:&&&&&& 8 bytes] 20
[c:&&&&&& 4 bytes] 20&&&&&&&&&& [c:&&&&&& 4 bytes] 24
[a:&&&&&& 1 byte ] 21&&&&&&&&&& [a:&&&&&& 1 byte ] 25
[d:&&&&&& 1 byte ] 22&&&&&&&&&& [d:&&&&&& 1 byte ] 26
[padding: 2 bytes] 24 & & [padding: 2 bytes] 28
[f:&&&&&& 4 bytes] 28&&&&&&&&&& [f:&&&&&& 4 bytes] 32
[padding: 4 bytes] 32
<span style="color:#.& 父类和子类的实例成员
父类和子类的成员变量分开存放,先是父类的实例成员。父类实例成员变量结束之后,按4位对齐,随后接着子类实例成员变量。
&&& byte a;
classBextends A{
&&& byte b;
内存结构如下:
&&& 32 bit & & & & & & & & & & & & & & & 64bit &#43;UseCompressedOops
[HEADER:& 8 bytes]&8&&&&&& [HEADER: 12 bytes] 12
[a:&&&&&& 1 byte ]&9 & & & & & & & [a:&&&&&& 1 byte ] 13
[padding: 3 bytes] 12&&&&&& [padding: 3 bytes] 16
[b:&&&&&& 1 byte ] 13 & & & & & & [b:&&&&&&1 byte ] 17
[padding: 3 bytes] 16&&&&&& [padding: 7 bytes] 24
如果子类首个成员变量是long或者double等8字节数据类型,而父类结束时没有8位对齐。会把子类的小于8字节的实例成员先排列,直到能8字节对齐。
class B extends A{
内存结构如下:
&&& 32 bit & & & & & & & & & & & & & &64bit &#43;UseCompressedOops
[HEADER:& 8 bytes]&8&&&&&& [HEADER:& 8 bytes] 12
[a:&&&&&& 1 byte ] &9 & & & & & & &[a:&&&&&& 1 byte ] 13
[padding: 3 bytes] 12&&&&&& [padding: 3 bytes] 16
[c:&&&&&& 2 bytes] 14 & & & & & [b:&&&&&&8 bytes] 24
[d:&&&&&& 1 byte ] 15 & & & & & [c:&&&&&&4 byte ] 28
[padding: 1 byte ] 16&&&&&& [d:&&&&&&1 byte ] 29
[b:&&&&&& 8 bytes] 24 & & & & &[padding: 3 bytes] 32
上面的示例中,在32位的JVM上,B的2个实例成员c, d被提前了。
<span style="color:#.& 非静态的内部类,有一个隐藏的对外部类的引用。
3.1数组的内存占用大小
数组也是对象,故有对象的头部,另外数组还有一个记录数组长度的int类型,随后是每一个数组的元素:基本数据类型或者引用。8字节对齐。
32 位的机器上
byte[0] 8字节的对象头部,<span style="color:#字节的int长度,
12字节,对齐后是<span style="color:#字节,实际 byte[0] ~byte[4]都是16字节(每个byte的长度为1byte,byte[0]-byte[4]占用padding长度)。
64 位&#43;UseCompressedOops
byte[0] 是<span style="color:#字节大小(对象头:mark
word: 8byte, kclasspointer: 4byte, array sizeof: 4byte),byte[1] ~byte[8] 24字节大小。
64 位-UseCompressedOops
byte[0], 16字节头部,4字节的int长度信息,20字节,对齐后 24 字节。byte[0] ~ byte[4] 都是24字节。
计算一个数组对象的公式(-XX:UseCompressedOops)
The general rules forcomputing the size of an object on JVM are :
Arrays of boolean, byte, char, short, int: 2 * 4 (Object header)&#43; 4 (length-field) &#43; sizeof(primitiveType) * length -& align result up to amultiple of 8
Arrays of objects: 2 * 4 (Object header) &#43; 4 (length-field) &#43; 4(objectreference length) * array length -& align result up to a multiple of 8
Arrays of longs and doubles: 2 * 4 (Object header) &#43; 4 (length-field) &#43; 4 (deadspace due to alignment restrictions) &#43; 8 * length
java.lang.Object: 2 * 4 (Object header)&
other objects: sizeofSuperClass &#43; 8 * nrOfLongAndDoubleFields &#43; 4 *nrOfIntFloatAndObjectFields &#43; 2 * nrOfShortAndCharFields &#43; 1 *nrOfByteAndBooleanFields -& align result up to a multiple of 8
Arrays of boolean, byte, char, short, int: 2 * 8 (Object header)&#43; 4 (length-field) &#43; sizeof(primitiveType) * length -& align result up to amultiple of 8
Arrays of objects: 2 * 8 (Object header) &#43; 4 (length-field) &#43; 4 (dead space dueto alignment restrictions) &#43; 8 * length
Arrays of longs and doubles: 2 * 8 (Object header) &#43; 4 (length-field) &#43; 4 (deadspace due to alignment restrictions) &#43; 8 * length
java.lang.Object: 2 * 8 (Object header)
other objects: sizeofSuperClass &#43; 8 * nrOfLongDoubleAndObjectFields &#43; 4 &#43;nrOfntAndFloatFields &#43; 2 * nrOfShortAndCharFields &#43; 1 *nrOfByteAndBooleanFields -& align result up to a multiple of 8
Note thatan object might have unused space due to alignment at every inheritance level(e.g. imagine a class A with just a byte field and class B has A as it'ssuperclass and declares a byte field itself -& 14 bytes 'wasted on 64 bitsystem).
Inpractice 64 bit needs 30 to 50% more memory due to references being twice aslarge.&
3.2字符串大小
64 bit -UseCompressedOops
64 bit &#43;UseCompressedOops
<span style="color:#
<span style="color:#
<span style="color:#
<span style="color:#(引用)
<span style="color:#
<span style="color:#
<span style="color:#
<span style="color:#
<span style="color:#
<span style="color:#
<span style="color:#
<span style="color:#
<span style="color:#
<span style="color:#
<span style="color:#
<span style="color:#
<span style="color:#
<span style="color:#
<span style="color:#
<span style="color:#
<span style="color:#
不计算value引用的Retained heap size,字符串本身就需要
24 ~ 40字节大小。
一个newString(&a&);&#43;UseCompressedOops这个对象的空间大小为:<span style="color:#字节头部&#43;4*4
= 28字节对齐到32字节,然后value所指向的char数组头部比普通对象多<span style="color:#个byte来存放长度,<span style="color:#&#43;4&#43;2byte的字符=18,总大小为<span style="color:#&#43;18=46byte,对齐后就是48byte,其实即使你new
String()也会占这么大的空间,<span style="color:#&#43;16=44byte,因为有对齐,如果字符的长度是<span style="color:#个,那么就是<span style="color:#&#43;4&#43;16=32,也就是有<span style="color:#byte;
如果不开启指针压缩再算算:头部变成<span style="color:#byte &#43; 4*3个int数据 &#43; 8(<span style="color:#个指针)
= 36对齐到40byte,对应的char数组的头部变成<span style="color:#&#43;4
&#43; 2 = 22对齐到24byte,40&#43;24=64byte,也就是只有一个字符或者<span style="color:#个字符都会对齐到<span style="color:#byte,所以,你懂的,参数该怎么调,代码该怎么写,如果长度为<span style="color:#个字符的那么后面部分就会变成<span style="color:#&#43;4&#43;16=36对齐到<span style="color:#byte,<span style="color:#&#43;40=80byte,也就是说,抛开其他的引用空间(比如通过数组或集合类引用),如果你有<span style="color:#来个String,每个大小就装<span style="color:#个字符,就会有<span style="color:#K的大小
/zhanjindong/p/3757767.html
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:492639次
积分:6832
积分:6832
排名:第2197名
原创:150篇
转载:57篇
译文:19篇
评论:130条
(1)(2)(2)(1)(1)(3)(2)(1)(4)(1)(1)(3)(2)(1)(2)(2)(3)(1)(4)(1)(2)(1)(1)(2)(2)(2)(3)(3)(2)(1)(3)(5)(3)(2)(2)(3)(4)(4)(1)(3)(2)(1)(6)(3)(3)(4)(6)(5)(1)(2)(4)(1)(8)(8)(8)(2)(1)(4)(3)(2)(1)(6)(6)(3)(4)(2)(2)(11)(4)(4)(3)(3)(3)(7)(5)(4)(2)<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
您的访问请求被拒绝 403 Forbidden - ITeye技术社区
您的访问请求被拒绝
亲爱的会员,您的IP地址所在网段被ITeye拒绝服务,这可能是以下两种情况导致:
一、您所在的网段内有网络爬虫大量抓取ITeye网页,为保证其他人流畅的访问ITeye,该网段被ITeye拒绝
二、您通过某个代理服务器访问ITeye网站,该代理服务器被网络爬虫利用,大量抓取ITeye网页
请您点击按钮解除封锁&<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
您的访问请求被拒绝 403 Forbidden - ITeye技术社区
您的访问请求被拒绝
亲爱的会员,您的IP地址所在网段被ITeye拒绝服务,这可能是以下两种情况导致:
一、您所在的网段内有网络爬虫大量抓取ITeye网页,为保证其他人流畅的访问ITeye,该网段被ITeye拒绝
二、您通过某个代理服务器访问ITeye网站,该代理服务器被网络爬虫利用,大量抓取ITeye网页
请您点击按钮解除封锁&如何查看java对象所占的内存大小
我们为什么想要知道对象所占对内存的大小呢?
(1)做一些cache的时候,我们不可能把数据库的所有的数据都缓存到内存里面,我们要估计缓存的大小。
(2)内存泄露的时候,我们可以查看某些对象的大小来定位问题,当然还有其他的更有效的方式,比如使用MAT分析dump文件
(3)根据jvm的堆内存设置,我们可以知道最多可以创建多少个对象。
从jdk5开始,提供了Instrumentation API,它有一个叫做getObjectSize()的方法,但是,这个方法存在两个问题:
(1)不可以直接使用。必须要实现一个Instrumentation Agent,还得放到jar包里面。
(2)它只能返回单个对象的大小,不能返回内部包含的子对象的大小。
关于第一个问题,很好解决,在任何一个类里面声明一个&premain&方法,就可以把这个类做成是一个agent:
public class SizeOfAgent {
&&&&&&&& static I
&&&&&&&& /** initializes agent */
&&&&&&&& public static void premain(String agentArgs, Instrumentation instP) {
&&&&&&&&&&&&&&&& inst = instP;&&&&&&&&&&
&&&&&&&& }
jvm在启动的时候会调用premain()方法,同时会传递Instrumentation这个对象实例,要告诉jvm Instrumentation agent所在的类,需要把这个类打到jar包里面,
然后在manifest.mf这个文件设置一些属性:
Premain-Class: sizeof.agent.SizeOfAgent
Boot-Class-Path:
Can-Redefine-Classes: false
java应用在启动的时候,指定-javaagent参数:
java -javaagent:sizeofag.jar &Your main class&
拿到Instrumentation这个实例以后,就可以调用sizeOf()方法了:
public class SizeOfAgent {
&&&&&&&& static I
&&&&&&&& // ...
&&&&&&&& public static long sizeOf(Object o) {
&&&&&&&&&&&&&&&& return inst.getObjectSize(o);
&&&&&&&& }
然后可以使用反射来获取子对象的大小。
完整的代码如下:
package com.bj58.
import java.lang.instrument.I
import java.lang.reflect.A
import java.lang.reflect.F
import java.lang.reflect.M
import java.util.IdentityHashM
import java.util.M
import java.util.S
public class SizeOfAgent {
&&& static I
&&& /** initializes agent */
&&& public static void premain(String agentArgs, Instrumentation instP) {
&&&&&&& inst = instP;
&&&& * Returns object size without member sub-objects.
&&&& * @param o
&&&& *&&&&&&&&&&& object to get size of
&&&& * @return object size
&&& public static long sizeOf(Object o) {
&&&&&&& if (inst == null) {
&&&&&&&&&&& throw new IllegalStateException(
&&&&&&&&&&&&&&&&&&& &Can not access instrumentation environment.\n&
&&&&&&&&&&&&&&&&&&&&&&&&&&& + &Please check if jar file containing SizeOfAgent class is \n&
&&&&&&&&&&&&&&&&&&&&&&&&&&& + &specified in the java&#39;s \&-javaagent\& command line argument.&);
&&&&&&& return inst.getObjectSize(o);
&&&& * Calculates full size of object iterating over its hierarchy graph.
&&&& * @param obj
&&&& *&&&&&&&&&&& object to calculate size of
&&&& * @return object size
&&& public static long fullSizeOf(Object obj) {
&&&&&&& Map&Object, Object& visited = new IdentityHashMap&Object, Object&();
&&&&&&& Stack&Object& stack = new Stack&Object&();
&&&&&&& long result = internalSizeOf(obj, stack, visited);
&&&&&&& while (!stack.isEmpty()) {
&&&&&&&&&&& result += internalSizeOf(stack.pop(), stack, visited);
&&&&&&& visited.clear();
&&& private static boolean skipObject(Object obj, Map&Object, Object& visited) {
&&&&&&& if (obj instanceof String) {
&&&&&&&&&&& // skip interned string
&&&&&&&&&&& if (obj == ((String) obj).intern()) {
&&&&&&&&&&&&&&&
&&&&&&&&&&& }
&&&&&&& return (obj == null) // skip visited object
&&&&&&&&&&&&&&& || visited.containsKey(obj);
&&& private static long internalSizeOf(Object obj, Stack&Object& stack,
&&&&&&&&&&& Map&Object, Object& visited) {
&&&&&&& if (skipObject(obj, visited)) {
&&&&&&&&&&& return 0;
&&&&&&& visited.put(obj, null);
&&&&&&& long result = 0;
&&&&&&& // get size of object + primitive variables + member pointers
&&&&&&& result += SizeOfAgent.sizeOf(obj);
&&&&&&& // process all array elements
&&&&&&& Class clazz = obj.getClass();
&&&&&&& if (clazz.isArray()) {
&&&&&&&&&&& if (clazz.getName().length() != 2) {// skip primitive type array
&&&&&&&&&&&&&&& int length = Array.getLength(obj);
&&&&&&&&&&&&&&& for (int i = 0; i & i++) {
&&&&&&&&&&&&&&&&&&& stack.add(Array.get(obj, i));
&&&&&&&&&&&&&&& }
&&&&&&&&&&& }
&&&&&&&&&&&
&&&&&&& // process all fields of the object
&&&&&&& while (clazz != null) {
&&&&&&&&&&& Field[] fields = clazz.getDeclaredFields();
&&&&&&&&&&& for (int i = 0; i & fields. i++) {
&&&&&&&&&&&&&&& if (!Modifier.isStatic(fields[i].getModifiers())) {
&&&&&&&&&&&&&&&&&&& if (fields[i].getType().isPrimitive()) {
&&&&&&&&&&&&&&&&&&&&&&& // skip primitive fields
&&&&&&&&&&&&&&&&&&& } else {
&&&&&&&&&&&&&&&&&&&&&&& fields[i].setAccessible(true);
&&&&&&&&&&&&&&&&&&&&&&& try {
&&&&&&&&&&&&&&&&&&&&&&&&&&& // objects to be estimated are put to stack
&&&&&&&&&&&&&&&&&&&&&&&&&&& Object objectToAdd = fields[i].get(obj);
&&&&&&&&&&&&&&&&&&&&&&&&&&& if (objectToAdd != null) {
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& stack.add(objectToAdd);
&&&&&&&&&&&&&&&&&&&&&&&&&&& }
&&&&&&&&&&&&&&&&&&&&&&& } catch (IllegalAccessException ex) {
&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&& }
&&&&&&&&&&&&&&&&&&& }
&&&&&&&&&&&&&&& }
&&&&&&&&&&& }
&&&&&&&&&&& clazz = clazz.getSuperclass();
然后我们可以做一个测试:
public class Test {
&&& static class Person{
&&&&&&& private S
&&&&&&& private S
&&&&&&& public Person(int id, String name, String address) {
&&&&&&&&&&& this.id =
&&&&&&&&&&& this.name =
&&&&&&&&&&& this.address =
&&& public static void main(String[] args) throws Exception {
&&&&&&& Person p = new Person(12, &xujsh&,&bj&);
&&&&&&& long size = SizeOfAgent.fullSizeOf(p);
&&&&&&& System.out.println(size);
切换到命令行:
D:\workspace\objsize\src&java -version
java version &1.6.0_22&
Java(TM) SE Runtime Environment (build 1.6.0_22-b04)
Java HotSpot(TM) Client VM (build 17.1-b03, mixed mode, sharing)
D:\workspace\objsize\src&javac com/bj58/test/*.java
D:\workspace\objsize\src&jar -cvfm size.jar MANIFEST.MF com/bj58/test/*
标明清单(manifest)
增加:com/bj58/test/SizeOfAgent.class(读入= 3119) (写出= 1698)(压缩了 45%)
增加:com/bj58/test/SizeOfAgent.java(读入= 3147) (写出= 1204)(压缩了 61%)
增加:com/bj58/test/Test$Person.class(读入= 442) (写出= 305)(压缩了 30%)
增加:com/bj58/test/Test.class(读入= 692) (写出= 441)(压缩了 36%)
增加:com/bj58/test/Test.java(读入= 509) (写出= 290)(压缩了 43%)
D:\workspace\objsize\src&java -javaagent:size.jar com.bj58.test.Test
MANIFEST.MF:
Manifest-Version: 1.0
Main-Class: com.bj58.test.Test
Premain-Class: com.bj58.test.SizeOfAgent
Boot-Class-Path:
Can-Redefine-Classes: false
【注意】MANIFEST.MF文件的格式要求比较严格,每一行要满足:key:空格value回车
如何在web应用程序里面使用呢?
以我的tomcat为例,
(1)把size.jar上传tomcat的lib目录下面
(2)修改catalina.sh:
添加一行:
JAVA_OPTS=&$JAVA_OPTS -javaagent:$CATALINA_HOME/lib/size.jar&& //这一行是新添加的
if [ -z &$LOGGING_MANAGER& ]; then
& JAVA_OPTS=&$JAVA_OPTS -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager&
& JAVA_OPTS=&$JAVA_OPTS $LOGGING_MANAGER&
(3)在应用里面添加一个controler:
@Path(value = &/api/size&)
public ActionResult size() {
&&& Map&Long, List&Long&& map = ApiUtils.getHotindexBaidu();
&&& long size = SizeOfAgent.fullSizeOf(map);
&&& return new ApiActionResult(&size:&+size);
然后就可以用来访问了。
(window.slotbydup=window.slotbydup || []).push({
id: '2467140',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467141',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467143',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467148',
container: s,
size: '1000,90',
display: 'inlay-fix'

我要回帖

更多关于 对象成员占用内存 的文章

 

随机推荐