博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
java对象内存占用
阅读量:6992 次
发布时间:2019-06-27

本文共 8552 字,大约阅读时间需要 28 分钟。

一、前言

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

 

二、原文的扩充

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;    }    /**     * 直接计算当前对象占用空间大小,包括当前类及超类的基本类型实例字段大小、
*
* 引用类型实例字段引用大小、实例基本类型数组总占用空间、实例引用类型数组引用本身占用空间大小;
*
* 但是不包括超类继承下来的和当前类声明的实例引用字段的对象本身的大小、实例引用数组引用的对象本身的大小
*
* * @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 visited = new HashSet(); Deque 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 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())=16sizeOf(new A())=16sizeOf(new B())=24sizeOf(new B2())=24sizeOf(new B[3])=32sizeOf(new C())=24fullSizeOf(new C())=128sizeOf(new D())=32fullSizeOf(new D())=64sizeOf(new int[3])=32sizeOf(new Integer(1)=16sizeOf(new Integer[0])=16sizeOf(new Integer[1])=24sizeOf(new Integer[2])=24sizeOf(new Integer[3])=32sizeOf(new Integer[4])=32sizeOf(new A[3])=32sizeOf(new E())=24sizeOf(new F())=16fullSizeOf(new F())=16fullSizeOf(new F1())=40fullSizeOf(new F2())=40fullSizeOf(new F3())=48sizeOf(s)=24fullSizeOf(s)=16sizeOf(s)=24fullSizeOf(s)=24sizeOf(c)=16fullSizeOf(c)=16sizeOf(cs)=16fullSizeOf(cs)=16sizeOf(cs)=24fullSizeOf(cs)=24sizeOf(i)=16fullSizeOf(i)=16sizeOf(i)=16fullSizeOf(i)=16

 

转载于:https://www.cnblogs.com/yoyotl/p/8421287.html

你可能感兴趣的文章
SQL语句技巧:查询存在一个表而不在另一个表中的数据记录
查看>>
[jPlayer]一分钟部署jPlayer
查看>>
关于oracle动态视图v$datafile和v$datafile_header(转)
查看>>
关于composer
查看>>
WPF中的动画——(三)时间线(TimeLine)
查看>>
POJ 2387 Til the Cows Come Home (最短路+Dijkstra)
查看>>
无主之地1
查看>>
mysql查询处理顺序
查看>>
微信公众平台教程,注册申请、认证、开发、推广营销,教你怎么用微信公众号...
查看>>
Senparc.Weixin.MP SDK 微信公众平台开发教程(十三):地图相关接口说明
查看>>
SQL Server2008 删除登录记录
查看>>
js数字验证
查看>>
Nginx 配置指令的执行顺序(九)
查看>>
【百度地图API】如何激发手机的高分辨率
查看>>
DIV+CSS专题:十天学会DIV+CSS
查看>>
2015第5周日
查看>>
输入法之模型剪枝一(基于熵的剪枝)
查看>>
《全体育&#183;瑜伽》
查看>>
UML中类图的符号解释
查看>>
HDU 4421 Bit Magic (图论-2SAT)
查看>>