java对象内存占用
一、前言
想知道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对象内存占用的更多相关文章
- Java 对象内存占用
java基本类型及对象占用的内存大小 请参考下面文章 原始类型及对象占用的内存大小 http://www.javamex.com/tutorials/memory/object_memory_usag ...
- 一个Java对象到底占用多大内存?
最近在读<深入理解Java虚拟机>,对Java对象的内存布局有了进一步的认识,于是脑子里自然而然就有一个很普通的问题,就是一个Java对象到底占用多大内存? 在网上搜到了一篇博客讲的非常好 ...
- 一个Java对象到底占用多大内存
在网上搜到了一篇博客讲的非常好,里面提供的这个类也非常实用: import java.lang.instrument.Instrumentation; import java.lang.reflect ...
- Ehcache计算Java对象内存大小
在EHCache中,可以设置maxBytesLocalHeap.maxBytesLocalOffHeap.maxBytesLocalDisk值,以控制Cache占用的内存.磁盘的大小(注:这里Off ...
- java对象内存大小评估
Java对象的内存布局:对象头(Header).实例数据(Instance Data)和对齐填充(Padding).无论是32位还是64位的HotSpot,使用的都是8字节对齐.也就是说每个java对 ...
- Java对象内存模型
2 Java对象内存模型 在HotSpot虚拟机中,对象在内存中存储的布局可以分为3块区域:对象头(Header). 实例数据(Instance Data)和对齐填充(Padding). 在 JVM ...
- JAVA 对象内存结构
JAVA对象内存结构 HotSpot虚拟机中,对象在内存中存储的布局可以分为三块区域:对象头(Header).实例数据(Instance Data)和对齐填充(Padding). 对象头 markWo ...
- Synchronized加锁、锁升级和java对象内存结构
首先了解一下JMM中定义的内存操作: 一个线程操作数据时候都是从主内存(堆内存)读取到自己工作内存(线程私有的数据区域)中再进行操作.对于硬件内存来说,并没有工作内存和主内存的区分,这都是java内存 ...
- Java对象内存布局
本文转载自Java对象内存布局 导语 首先直接抛出问题 Unsafe.getInt(obj, fieldOffset)中的fieldOffset是什么, 类似还有compareAndSwapX(obj ...
随机推荐
- 使用jstl报错:Can not find the tag library descriptor for “http://java.sun.com/jstl/core”
使用jstl报错:Can not find the tag library descriptor for “http://java.sun.com/jstl/core” 出现这个错误的原因是项目中没有 ...
- WinForm 之 程序退出
一.关闭窗体 在c#中退出WinForm程序包括有很多方法,如:this.Close(); Application.Exit();Application.ExitThread(); System.En ...
- JS 处理Json数据事例
JS从远端获取数据之后,往往还需要在处理一下,下面给出一个事例,供参考 将'[{"role_id":1,"enable":1},{"role_id&q ...
- 【转】Window 通过cmd查看端口占用、相应进程、杀死进程等的命令
转自:http://blog.csdn.net/jiangwei0910410003/article/details/18967441 一. 查看所有进程占用的端口 在开始-运行-cmd,输入:ne ...
- python中string和十六进制、二进制互转
def str_to_hex(s): return ' '.join([hex(ord(c)).replace('0x', '') for c in s]) def hex_to_str(s): re ...
- Java的一个关于“星球”的枚举
public enum Planet { /** * 水星 */ MERCURY(3.302e+23, 2.439e6), /** * 金星 */ VENUS(4.869e+24, 6.052e6), ...
- Window修改cmd编码
Window默认编码是gbk,对一些字符不支持.需在不同语言上切换,急需要调整字符集编码..chcp 功能: 显示或设置活动代码页编号 chcp [nnn] #nnn 指定的代码页编号 chcp ...
- 使用PowerDesigner生成SQL语句
0.我使用的PowerDedigner的版本如下: 1.tools>>Resource>>DBMS,然后选中你的数据库版本,双击或点击左上角的properties. 2.再选择 ...
- poj 2632 Crashing Robots(模拟)
链接:poj 2632 题意:在n*m的房间有num个机器,它们的坐标和方向已知,现给定一些指令及机器k运行的次数, L代表机器方向向左旋转90°,R代表机器方向向右旋转90°,F表示前进,每次前进一 ...
- ios中在uiNavigationcontroller中做转场动画
1:了解,当创建一个UINavigationcontroller中时,当创建一个子视图控制器压入uiNavigationController中,其中里面的view也别加入UINavigationcon ...