`
soleghost
  • 浏览: 40802 次
  • 性别: Icon_minigender_1
  • 来自: 未知
社区版块
存档分类
最新评论

如何计算java内存大小--谁吃了对象引用的16byte?

阅读更多
public class ResidenceRulesDO {

    /**
     * This property corresponds to db column <tt>BEGIN_CODE</tt>.
     */
    private long              beginCode;

    /**
     * This property corresponds to db column <tt>END_CODE</tt>.
     */
    private long              endCode;

    /**
     * This property corresponds to db column <tt>NATION</tt>.
     */
    private String            nation;

    /**
     * This property corresponds to db column <tt>PROVINCE</tt>.
     */
    private String            province;

    /**
     * This property corresponds to db column <tt>CITY</tt>.
     */
    private String            city;

    /**
     * This property corresponds to db column <tt>MEMO</tt>.
     */
    private String            memo;

    /**
     * This property corresponds to db column <tt>GMT_CREATE</tt>.
     */
    private Date              gmtCreate;

    /**
     * This property corresponds to db column <tt>GMT_MODIFIED</tt>.
     */
    private Date              gmtModified;

    //-----------------------setter/getter--------------------------

    public long getBeginCode() {
        return beginCode;
    }

    public void setBeginCode(long beginCode) {
        this.beginCode = beginCode;
    }

    public long getEndCode() {
        return endCode;
    }

    public void setEndCode(long endCode) {
        this.endCode = endCode;
    }

    public String getNation() {
        return nation;
    }

    public void setNation(String nation) {
        this.nation = nation;
    }

    public String getProvince() {
        return province;
    }

    public void setProvince(String province) {
        this.province = province;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    public String getMemo() {
        return memo;
    }

    public void setMemo(String memo) {
        this.memo = memo;
    }

    public Date getGmtCreate() {
        return gmtCreate;
    }

    public void setGmtCreate(Date gmtCreate) {
        this.gmtCreate = gmtCreate;
    }

    public Date getGmtModified() {
        return gmtModified;
    }

    public void setGmtModified(Date gmtModified) {
        this.gmtModified = gmtModified;
    }

}

 

这样一个对象,如何计算内存大小?

1.只new出一个ResidenceRulesDO 对象

a.通过规则计算

一个空对象占8个字节,一个引用占4个字节,一个long占8个字节

ResidenceRulesDO对象(8)+ 2个long型(8*2)+4个String引用(4*4)+2个Date引用(2*4)=48bytes

b.通过程序计算

此程序来源于http://www.javaworld.com/javaworld/javatips/jw-javatip130.html?page=1

 

import java.util.Date;

public class Sizeof {
    public static void main(String[] args) throws Exception {
        // Warm up all classes/methods we will use
        runGC();
        usedMemory();
        // Array to keep strong references to allocated objects
        final int count = 100000;
        Object[] objects = new Object[count];
        long heap1 = 0;
        // Allocate count+1 objects, discard the first one
        for (int i = -1; i < count; ++i) {
            ResidenceRulesDO object = null;
            // Instantiate your data here and assign it to object
            object = new ResidenceRulesDO();
//            object.setBeginCode(new Long(i));
//            object.setEndCode(new Long(i));
//            object.setProvince(new String());
//            object.setCity(new String());
//            object.setNation(new String());
//            object.setMemo(new String());
//            object.setGmtCreate(new Date());
//            object.setGmtModified(new Date());
            //object = new Integer (i);
            //object = new Long (i);
            //object = new String ();
            //object = new byte [128][1]
            if (i >= 0)
                objects[i] = object;
            else {
                object = null; // Discard the warm up object
                runGC();
                heap1 = usedMemory(); // Take a before heap snapshot
            }
        }
        runGC();
        long heap2 = usedMemory(); // Take an after heap snapshot:

        final int size = Math.round(((float) (heap2 - heap1)) / count);
        System.out.println("'before' heap: " + heap1 + ", 'after' heap: " + heap2);
        System.out.println("heap delta: " + (heap2 - heap1) + ", {" + objects[0].getClass()
                           + "} size = " + size + " bytes");

        for (int i = 0; i < count; ++i) {
            objects[i] = null;
        }

        objects = null;
    }

    private static void runGC() throws Exception {
        // It helps to call Runtime.gc()
        // using several method calls:
        for (int r = 0; r < 4; ++r)
            _runGC();
    }

    private static void _runGC() throws Exception {
        long usedMem1 = usedMemory(), usedMem2 = Long.MAX_VALUE;
        for (int i = 0; (usedMem1 < usedMem2) && (i < 500); ++i) {
            s_runtime.runFinalization();
            s_runtime.gc();
            Thread.currentThread().yield();

            usedMem2 = usedMem1;
            usedMem1 = usedMemory();
        }
    }

    private static long usedMemory() {
        return s_runtime.totalMemory() - s_runtime.freeMemory();
    }

    private static final Runtime s_runtime = Runtime.getRuntime();
} // End of class

 

输出结果:

 

'before' heap: 668176, 'after' heap: 5466520
heap delta: 4798344, {class com.alipay.cif.core.dal.dataobject.ResidenceRulesDO} size = 48 bytes

 

两者计算相同。

 

 

 

2.如果是赋值的ResidenceRulesDO呢?

比如此对象为

            object = new ResidenceRulesDO();
            object.setBeginCode(new Long(i));
            object.setEndCode(new Long(i));
            object.setProvince(new String());
            object.setCity(new String());
            object.setNation(new String());
            object.setMemo(new String());
            object.setGmtCreate(new Date());
            object.setGmtModified(new Date());

 

 a.通过算法计算

此前算出来的空对象(48)+2个Long值(16*2)+4个String(40*4)+2个Date(24*2)=288

 

b.通过程序计算

import java.util.Date;

public class Sizeof {
    public static void main(String[] args) throws Exception {
        // Warm up all classes/methods we will use
        runGC();
        usedMemory();
        // Array to keep strong references to allocated objects
        final int count = 100000;
        Object[] objects = new Object[count];
        long heap1 = 0;
        // Allocate count+1 objects, discard the first one
        for (int i = -1; i < count; ++i) {
            ResidenceRulesDO object = null;
            // Instantiate your data here and assign it to object
            object = new ResidenceRulesDO();
            object.setBeginCode(new Long(i));
            object.setEndCode(new Long(i));
            object.setProvince(new String());
            object.setCity(new String());
            object.setNation(new String());
            object.setMemo(new String());
            object.setGmtCreate(new Date());
            object.setGmtModified(new Date());
            //object = new Integer (i);
            //object = new Long (i);
            //object = new String ();
            //object = new byte [128][1]
            if (i >= 0)
                objects[i] = object;
            else {
                object = null; // Discard the warm up object
                runGC();
                heap1 = usedMemory(); // Take a before heap snapshot
            }
        }
        runGC();
        long heap2 = usedMemory(); // Take an after heap snapshot:

        final int size = Math.round(((float) (heap2 - heap1)) / count);
        System.out.println("'before' heap: " + heap1 + ", 'after' heap: " + heap2);
        System.out.println("heap delta: " + (heap2 - heap1) + ", {" + objects[0].getClass()
                           + "} size = " + size + " bytes");

        for (int i = 0; i < count; ++i) {
            objects[i] = null;
        }

        objects = null;
    }

    private static void runGC() throws Exception {
        // It helps to call Runtime.gc()
        // using several method calls:
        for (int r = 0; r < 4; ++r)
            _runGC();
    }

    private static void _runGC() throws Exception {
        long usedMem1 = usedMemory(), usedMem2 = Long.MAX_VALUE;
        for (int i = 0; (usedMem1 < usedMem2) && (i < 500); ++i) {
            s_runtime.runFinalization();
            s_runtime.gc();
            Thread.currentThread().yield();

            usedMem2 = usedMem1;
            usedMem1 = usedMemory();
        }
    }

    private static long usedMemory() {
        return s_runtime.totalMemory() - s_runtime.freeMemory();
    }

    private static final Runtime s_runtime = Runtime.getRuntime();
} // End of class

 

输出:

'before' heap: 669120, 'after' heap: 26267784
heap delta: 25598664, {class com.alipay.cif.core.dal.dataobject.ResidenceRulesDO} size = 256 bytes

 

 

 两种算法的差别在哪里呢?

经过程序的调试,2个Long型设置与不设置值,都不影响整个对象的内存的大小,

正好288-256=2*16(2个Long)一致

 

为什么在对象中,引用到的Long对象不占空间呢?而单独计算Long对象却要16个byte?与常量池有关系吗?路漫漫其修远,还需慢慢探索啊! 

分享到:
评论
1 楼 teasp 2013-05-07  
哪有两个Long啊?分明是两个long,这是原始类型,它们所占空间是固定的,你没给它赋值,它也有个0值啊。

相关推荐

    Java面试宝典-经典

    一. Java基础部分 7 1、一个".java"源文件中是否可以包括多个...7、如何给weblogic指定大小的内存? 129 8、如何设定的weblogic的热启动模式(开发模式)与产品发布模式? 129 9、如何启动时不需输入用户名与密码? 130 10、...

    新版Android开发教程.rar

    � 采用了对有限内存、电池和 CPU 优化过的虚拟机 Dalvik , Android 的运行速度比想象的要快很多。 � 运营商(中国移动等)的大力支持,产业链条的热捧。 � 良好的盈利模式( 3/7 开),产业链条的各方:运营商、...

    JAVA面试题最全集

    方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。这个方法是由垃圾收集器在确定这个对象没有被引用时对这个对象调用的。它是在 Object 类中定义的,因此所有的类都继承了它。子类覆盖 finalize() ...

    黑马程序员 安卓学院 万元哥项目经理 分享220个代码实例

    |--应用之获得占用内存大小 |--应用之通过包名开启一个应用 |--应用之隐式意图开启设置界面 |--应用启动之检查版本更新及初始化 |--延时任务的工具类 |--异常之UncaughtExceptionHandler全局捕获处理 |--异步任务...

    java面试宝典

    java面试试题 全面 准确 带答案 ...245、 如何给weblogic指定大小的内存? 56 246、如何设定的weblogic的热启动模式(开发模式)与产品发布模式? 57 247、如何启动时不需输入用户名与密码? 57 248、在...

    java 面试题 总结

    对象引用实例变量的缺省值为 null,而原始类型实例变量的缺省值与它们的类型有关。 4、String 和StringBuffer的区别 JAVA平台提供了两个类:String和StringBuffer,它们可以储存和操作字符串,即包含多个字符的字符...

    超级有影响力霸气的Java面试题大全文档

    对象引用实例变量的缺省值为 null,而原始类型实例变量的缺省值与它们的类型有关。 7、String 和StringBuffer的区别  JAVA平台提供了两个类:String和StringBuffer,它们可以储存和操作字符串,即包含多个字符的...

    Java面试宝典2010版

    一. Java基础部分 7 1、一个".java"源文件中是否可以包括多个...7、如何给weblogic指定大小的内存? 129 8、如何设定的weblogic的热启动模式(开发模式)与产品发布模式? 129 9、如何启动时不需输入用户名与密码? 130 10、...

    java面试题

    对象引用遍历 43 63.2. 几种垃圾回收机制 43 63.2.1. 标记-清除收集器 43 63.2.2. 标记-压缩收集器 43 63.2.3. 复制收集器 44 63.2.4. 增量收集器 44 63.2.5. 分代收集器 44 63.2.6. 并发收集器 44 63.2.7. 并行...

    java面试题大全(2012版)

    2012版最全面试题大全目录: 一. Java基础部分 7 1、一个".java"源文件中是否可以包括多个...7、如何给weblogic指定大小的内存? 129 8、如何设定的weblogic的热启动模式(开发模式)与产品发布模式? 129 9、如何启动时不...

    java基础题 很全面

    13. 如何给weblogic指定大小的内存? 22 14. 如何设定的weblogic的热启动模式(开发模式)与产品发布模式? 22 15. 如何启动时不需输入用户名与密码? 22 16. 在weblogic管理制台中对一个应用域(或者说是一个网站,Domain)...

    最新Java面试宝典pdf版

    一. Java基础部分 7 1、一个".java"源文件中是否可以包括多个...7、如何给weblogic指定大小的内存? 129 8、如何设定的weblogic的热启动模式(开发模式)与产品发布模式? 129 9、如何启动时不需输入用户名与密码? 130 10、...

    Java面试笔试资料大全

    一. Java基础部分 7 1、一个".java"源文件中是否可以包括多个...7、如何给weblogic指定大小的内存? 129 8、如何设定的weblogic的热启动模式(开发模式)与产品发布模式? 129 9、如何启动时不需输入用户名与密码? 130 10、...

    java面试宝典2012

    10、使用final关键字修饰一个变量时,是引用不能变,还是引用的对象不能变? 11 11、"=="和equals方法究竟有什么区别? 12 12、静态变量和实例变量的区别? 13 13、是否可以从一个static方法内部发出对非static方法...

    JAVA面试宝典2010

    一. Java基础部分 7 1、一个".java"源文件中是否可以包括多个...7、如何给weblogic指定大小的内存? 129 8、如何设定的weblogic的热启动模式(开发模式)与产品发布模式? 129 9、如何启动时不需输入用户名与密码? 130 10、...

    Java面试宝典2012新版

    一. Java基础部分 7 1、一个".java"源文件中是否可以包括多个类(不是内部类)?...7、如何给weblogic指定大小的内存? 129 8、如何设定的weblogic的热启动模式(开发模式)与产品发布模式? 129 9、如何启动...

    Java面试宝典2012版

    10、使用final关键字修饰一个变量时,是引用不能变,还是引用的对象不能变? 11 11、"=="和equals方法究竟有什么区别? 11 12、静态变量和实例变量的区别? 12 13、是否可以从一个static方法内部发出对非static...

    操作系统(内存管理)

    文中将为您提供如何管理内存的细节,然后将进一步展示如何手工管理内存,如何使用引用计数或者内存池来半手工地管理内存,以及如何使用垃圾收集自动管理内存。 为什么必须管理内存 内存管理是计算机编程最为基本的...

Global site tag (gtag.js) - Google Analytics