一、前言
想知道java对象在内存中的占用情况吗?感谢这位大神的无私分享。

http://yueyemaitian.iteye.com/blog/2033046

二、原文的扩充
1. 增加了代理jar包的打包脚本及过程
2. 增加了测试脚本的示例

三、查看字节工具类

import java.lang.instrument.Instrumentation;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.HashSet;
import java.util.Set; /**
* 对象占用字节大小工具类
*
* @author tianmai.fh
* @date 2014-03-18 11:29
*/
public class SizeOfObject {
static Instrumentation inst; public static void premain(String args, Instrumentation instP) {
inst = instP;
} /**
* 直接计算当前对象占用空间大小,包括当前类及超类的基本类型实例字段大小、<br>
* </br>
* 引用类型实例字段引用大小、实例基本类型数组总占用空间、实例引用类型数组引用本身占用空间大小;<br>
* </br>
* 但是不包括超类继承下来的和当前类声明的实例引用字段的对象本身的大小、实例引用数组引用的对象本身的大小 <br>
* </br>
*
* @param obj
* @return
*/
public static long sizeOf(Object obj) {
return inst.getObjectSize(obj);
} /**
* 递归计算当前对象占用空间总大小,包括当前类和超类的实例字段大小以及实例字段引用对象大小
*
* @param objP
* @return
* @throws IllegalAccessException
*/
public static long fullSizeOf(Object objP) throws IllegalAccessException {
Set<Object> visited = new HashSet<Object>();
Deque<Object> toBeQueue = new ArrayDeque<>();
toBeQueue.add(objP);
long size = 0L;
while (toBeQueue.size() > 0) {
Object obj = toBeQueue.poll();
// sizeOf的时候已经计基本类型和引用的长度,包括数组
size += skipObject(visited, obj) ? 0L : sizeOf(obj);
Class<?> tmpObjClass = obj.getClass();
if (tmpObjClass.isArray()) {
// [I , [F 基本类型名字长度是2
if (tmpObjClass.getName().length() > 2) {
for (int i = 0, len = Array.getLength(obj); i < len; i++) {
Object tmp = Array.get(obj, i);
if (tmp != null) {
// 非基本类型需要深度遍历其对象
toBeQueue.add(Array.get(obj, i));
}
}
}
} else {
while (tmpObjClass != null) {
Field[] fields = tmpObjClass.getDeclaredFields();
for (Field field : fields) {
if (Modifier.isStatic(field.getModifiers()) // 静态不计
|| field.getType().isPrimitive()) { // 基本类型不重复计
continue;
} field.setAccessible(true);
Object fieldValue = field.get(obj);
if (fieldValue == null) {
continue;
}
toBeQueue.add(fieldValue);
}
tmpObjClass = tmpObjClass.getSuperclass();
}
}
}
return size;
} /**
* String.intern的对象不计;计算过的不计,也避免死循环
*
* @param visited
* @param obj
* @return
*/
static boolean skipObject(Set<Object> visited, Object obj) {
if (obj instanceof String && obj == ((String) obj).intern()) {
return true;
}
return visited.contains(obj);
}
}

四、打成工具类jar包

1. 编译class文件

javac -encoding utf8 com/your/package/SizeOfObject.java

2. 编写menifest文件

Premain-class: com.your.package.SizeOfObject
Can-Redefine-Classes: false
Boot-Class-Path:

3. 打包

jar -cmf manifest agent.jar com/your/package/SizeOfObject.class

3.1 manifest在当前目录下

3.2 agent.jar为生成的jar包名称

3.3 class为步骤1编译成的文件

五、测试类文件

import static com.tuniu.study.SizeOfObject.fullSizeOf;
import static com.tuniu.study.SizeOfObject.sizeOf;
/**
* @author tianmai.fh
* @date 2014-03-18 20:17
*/
public class SizeOfObjectTest {
/**
* -XX:+UseCompressedOops: mark/4 + metedata/8 + 4 = 16
* -XX:-UseCompressedOops: mark/8 + metedata/8 + 4 + padding/4 = 24
*/
static class A {
int a;
} /**
* -XX:+UseCompressedOops: mark/4 + metedata/8 + 4 + 4 + padding/4 = 24
* -XX:-UseCompressedOops: mark/8 + metedata/8 + 4 + 4 = 24
*/
static class B {
int a;
int b;
} /**
* -XX:+UseCompressedOops: mark/4 + metedata/8 + 4 + 4 + padding/4 = 24
* -XX:-UseCompressedOops: mark/8 + metedata/8 + 8 + 4 + padding/4 = 32
*/
static class B2 {
int b2a;
Integer b2b;
} /**
* 不考虑对象头:
* 4 + 4 + 4 * 3 + 3 * sizeOf(B)
*/
static class C extends A {
int ba;
B[] as = new B[3]; C() {
for (int i = 0; i < as.length; i++) {
as[i] = new B();
}
}
} static class D extends B {
int da;
Integer[] di = new Integer[3];
} /**
* 会算上A的实例字段
*/
static class E extends A {
int ea;
int eb;
} static class F {
String s;
} static class F1 {
String s = "1";
} static class F2 {
String s = "12";
} static class F3 {
String s = "12345678";
} public static void main(String[] args) throws IllegalAccessException { System.out.println("sizeOf(new Object())=" + sizeOf(new Object()));
System.out.println("sizeOf(new A())=" + sizeOf(new A()));
System.out.println("sizeOf(new B())=" + sizeOf(new B()));
System.out.println("sizeOf(new B2())=" + sizeOf(new B2()));
System.out.println("sizeOf(new B[3])=" + sizeOf(new B[3]));
System.out.println("sizeOf(new C())=" + sizeOf(new C()));
System.out.println("fullSizeOf(new C())=" + fullSizeOf(new C()));
System.out.println("sizeOf(new D())=" + sizeOf(new D()));
System.out.println("fullSizeOf(new D())=" + fullSizeOf(new D()));
System.out.println("sizeOf(new int[3])=" + sizeOf(new int[3]));
System.out.println("sizeOf(new Integer(1)=" + sizeOf(new Integer(1)));
System.out.println("sizeOf(new Integer[0])=" + sizeOf(new Integer[0]));
System.out.println("sizeOf(new Integer[1])=" + sizeOf(new Integer[1]));
System.out.println("sizeOf(new Integer[2])=" + sizeOf(new Integer[2]));
System.out.println("sizeOf(new Integer[3])=" + sizeOf(new Integer[3]));
System.out.println("sizeOf(new Integer[4])=" + sizeOf(new Integer[4]));
System.out.println("sizeOf(new A[3])=" + sizeOf(new A[3]));
System.out.println("sizeOf(new E())=" + sizeOf(new E()));
System.out.println("sizeOf(new F())=" + sizeOf(new F()));
System.out.println("fullSizeOf(new F())=" + fullSizeOf(new F()));
System.out.println("fullSizeOf(new F1())=" + fullSizeOf(new F1()));
System.out.println("fullSizeOf(new F2())=" + fullSizeOf(new F2()));
System.out.println("fullSizeOf(new F3())=" + fullSizeOf(new F3())); String s = "";
System.out.println("sizeOf(s)=" + sizeOf(s));
System.out.println("fullSizeOf(s)=" + fullSizeOf(s));
s = "1";
System.out.println("sizeOf(s)=" + sizeOf(s));
System.out.println("fullSizeOf(s)=" + fullSizeOf(s));
char c = '0';
System.out.println("sizeOf(c)=" + sizeOf(c));
System.out.println("fullSizeOf(c)=" + fullSizeOf(c));
char[] cs = new char[] {};
System.out.println("sizeOf(cs)=" + sizeOf(cs));
System.out.println("fullSizeOf(cs)=" + fullSizeOf(cs));
cs = new char[] {'0','1'};
System.out.println("sizeOf(cs)=" + sizeOf(cs));
System.out.println("fullSizeOf(cs)=" + fullSizeOf(cs)); int i = 0;
System.out.println("sizeOf(i)=" + sizeOf(i));
System.out.println("fullSizeOf(i)=" + fullSizeOf(i));
i = 1000000;
System.out.println("sizeOf(i)=" + sizeOf(i));
System.out.println("fullSizeOf(i)=" + fullSizeOf(i)); }
}

打包成可执行jar包。(我用的eclipse...export...轻松愉快)

六、运行测试

1. 运行命令

java -javaagent:sizeOf_lib/agent.jar -jar sizeOf.jar

2. 运行结果

sizeOf(new Object())=16
sizeOf(new A())=16
sizeOf(new B())=24
sizeOf(new B2())=24
sizeOf(new B[3])=32
sizeOf(new C())=24
fullSizeOf(new C())=128
sizeOf(new D())=32
fullSizeOf(new D())=64
sizeOf(new int[3])=32
sizeOf(new Integer(1)=16
sizeOf(new Integer[0])=16
sizeOf(new Integer[1])=24
sizeOf(new Integer[2])=24
sizeOf(new Integer[3])=32
sizeOf(new Integer[4])=32
sizeOf(new A[3])=32
sizeOf(new E())=24
sizeOf(new F())=16
fullSizeOf(new F())=16
fullSizeOf(new F1())=40
fullSizeOf(new F2())=40
fullSizeOf(new F3())=48
sizeOf(s)=24
fullSizeOf(s)=16
sizeOf(s)=24
fullSizeOf(s)=24
sizeOf(c)=16
fullSizeOf(c)=16
sizeOf(cs)=16
fullSizeOf(cs)=16
sizeOf(cs)=24
fullSizeOf(cs)=24
sizeOf(i)=16
fullSizeOf(i)=16
sizeOf(i)=16
fullSizeOf(i)=16

java对象内存占用的更多相关文章

  1. Java 对象内存占用

    java基本类型及对象占用的内存大小 请参考下面文章 原始类型及对象占用的内存大小 http://www.javamex.com/tutorials/memory/object_memory_usag ...

  2. 一个Java对象到底占用多大内存?

    最近在读<深入理解Java虚拟机>,对Java对象的内存布局有了进一步的认识,于是脑子里自然而然就有一个很普通的问题,就是一个Java对象到底占用多大内存? 在网上搜到了一篇博客讲的非常好 ...

  3. 一个Java对象到底占用多大内存

    在网上搜到了一篇博客讲的非常好,里面提供的这个类也非常实用: import java.lang.instrument.Instrumentation; import java.lang.reflect ...

  4. Ehcache计算Java对象内存大小

    在EHCache中,可以设置maxBytesLocalHeap.maxBytesLocalOffHeap.maxBytesLocalDisk值,以控制Cache占用的内存.磁盘的大小(注:这里Off ...

  5. java对象内存大小评估

    Java对象的内存布局:对象头(Header).实例数据(Instance Data)和对齐填充(Padding).无论是32位还是64位的HotSpot,使用的都是8字节对齐.也就是说每个java对 ...

  6. Java对象内存模型

    2 Java对象内存模型 在HotSpot虚拟机中,对象在内存中存储的布局可以分为3块区域:对象头(Header). 实例数据(Instance Data)和对齐填充(Padding). 在 JVM ...

  7. JAVA 对象内存结构

    JAVA对象内存结构 HotSpot虚拟机中,对象在内存中存储的布局可以分为三块区域:对象头(Header).实例数据(Instance Data)和对齐填充(Padding). 对象头 markWo ...

  8. Synchronized加锁、锁升级和java对象内存结构

    首先了解一下JMM中定义的内存操作: 一个线程操作数据时候都是从主内存(堆内存)读取到自己工作内存(线程私有的数据区域)中再进行操作.对于硬件内存来说,并没有工作内存和主内存的区分,这都是java内存 ...

  9. Java对象内存布局

    本文转载自Java对象内存布局 导语 首先直接抛出问题 Unsafe.getInt(obj, fieldOffset)中的fieldOffset是什么, 类似还有compareAndSwapX(obj ...

随机推荐

  1. Swift语言精要 - 序列化和反序列化

    在swift中你可以把一个对象转换成为数据,你所要做的就是 首先,你需要让对象实现NSObject和NSCoding协议. 其次,实现以下两个方法: encodeWithCoder init(code ...

  2. C# 通过SendMessage获取浏览器地址栏的地址

    1:通过SPY++获得地址栏的层次结构,然后一层一层获得 2:代码 using System; using System.Collections.Generic; using System.Linq; ...

  3. tail -f 和tail -F的区别

    http://flume.apache.org/FlumeUserGuide.html flume抓取 exec 的command 官网有如下建议:

  4. mysql的逻辑结构

    mysql 数据库的逻辑架构如下图: 第一层,即最上一层,所包含的服务并不是MySQL所独有的技术.它们都是服务于C/S程序或者是这些程序所需要的 :连接处理,身份验证,安全性等等. 第二层值得关注. ...

  5. numpy 傅立叶得到幅值和频率

    做个备份,对 numpy 不熟,每次都找函数找半天. 代码里分几块: 1. 从 argc[1] 的文档中读取数据,并转化为 float.文档中有 2001 行,第一行为头,后面 2000 个是采样数据 ...

  6. std::thread中获取当前线程的系统id

    std::thread不提供获取当前线程的系统id的方法,仅可以获取当前的线程id,但是我们可以通过建立索引表的方式来实现 std::mutex m; std::map<std::thread: ...

  7. django之创建第4-3个项目-访问list数据

    1.index <!DOCTYPE html> <html lang="en"> <head> <meta charset="U ...

  8. linux下挂载VHD等虚拟磁盘文件

    1.RAW格式虚拟磁盘 linux下可以直接挂载raw格式的虚拟磁盘镜像文件. 例如,这里先用dd命令创建一个文件,然后将其格式化为ext4格式(只有一个分区),然后挂载到/mnt目录. 下面的raw ...

  9. 转:Ogre源码剖析 - 场景管理之Octree

    由于本人的引擎ProjectGaia服务于08年创新杯的游戏项目 – 3D太空游戏,所以理所应当加入Octree(八叉树 – 已经周宁学长发帖介绍过)场景管理器.参考了无数Octree的代码,发现还是 ...

  10. 俄罗斯方块-C语言-详注版

    代码地址如下:http://www.demodashi.com/demo/14818.html 俄罗斯方块-C语言-详注版 概述 本文详述了C语言版俄罗斯方块游戏的原理以及实现方法,对游戏代码进行了详 ...