`
soleghost
  • 浏览: 41843 次
  • 性别: 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编程环境中,了解对象占用的内存大小是优化性能的关键步骤。这可以帮助我们避免内存泄漏,提高应用程序的效率。本文将深入探讨如何统计缓存(尤其是Java对象)所占的内存大小,以及这对理解程序内存消耗的重要...

    计算一个Java对象占用字节数的方法

    本篇文章将深入探讨如何计算Java对象占用的内存字节数,以及影响这一数值的因素。 首先,Java对象在堆内存中由四个部分组成:对象头(A)、基本类型域(B)、引用类型域(C)和填充物(D)。 **对象头(A)**: ...

    Java 对象(数组)占多大空间(几个字节) 手把手做实验

    首先,`-XX:+UseCompressedOops`(Ordinary Object Pointers)参数是默认开启的,它使得64位JVM在32GB以下堆内存时,将对象引用由64位压缩为32位,从而节省内存。`-XX:+UseCompressedClassPointers`则对类的元数据引用...

    java-JAVA-电子教案.pdf

    Java为每种数据类型提供了固定的内存大小,这是Java语言“一次编写,到处运行”的重要特性之一。 Java语言中的运算符用于执行数据运算,包括算术运算符(如加减乘除)、关系运算符(如大于、小于)、逻辑运算符(如...

    java内存管理总结

    ### Java内存管理总结 #### 一、Java如何管理内存 Java的内存管理主要涉及对象的分配和释放。这一过程分为两个部分:分配和释放。 **分配:** - 内存的分配是由程序通过关键字`new`来完成的,用于为每个对象申请...

    Java的内存机制

    1. **Java内存管理** - **内存分配**:在Java中,内存的分配主要由程序通过`new`关键字来完成。对象都分配在堆内存(Heap)中,而基本数据类型(如int, short, long, byte, float, double, boolean, char)的实例则...

    (超赞)JAVA精华之--深入JAVA API

    - 字符串常量 `"hello"` 实际上是匿名对象的一个引用。当使用相同的字符串字面量创建多个字符串时,它们实际上共享同一内存地址。 - 使用 `new String()` 创建的字符串则是不同的对象,即使内容相同也不会共享内存...

    Java虚拟机内存管理总结

    堆的优势是可以动态分配内存大小,生存期也不必事先告诉编译器,因为它是在运行时动态分配内存的。缺点就是要在运行时动态分配内存,存取速度较慢;栈的优势是,存取速度比堆要快,仅次于直接位于CPU中的寄存器。...

    java 对象在内存中的结构

    堆是 Java 程序员第二常用的存储区域,堆的优势是可以动态地分配内存大小,生存期也不必事先告诉编译器,Java 的垃圾收集器会自动收走这些不再使用的数据。但缺点是,由于要在运行时动态分配内存,存取速度较慢。堆...

    java中内存分配

    堆的优势是可以动态地分配内存大小,生存期也不必事先告诉编译器,Java 的垃圾收集器会自动收走这些不再使用的数据。但缺点是,由于要在运行时动态分配内存存取速度较慢。 在 Java 中,基本数据类型共有 8 种,即 ...

    Java占用内存的研究.pdf

    例如,对象的内存大小总是8的倍数,这意味着即使一个对象的理论内存大小是41字节,它仍然会占用48字节的内存空间,因为JVM会进行向上对齐。 总结而言,本文档提供了一个深入的分析,帮助读者理解在Java编程中,不同...

    JAVA内存分配

    ### JAVA内存分配详解 #### 一、JAVA内存结构概述 Java程序在运行过程中涉及的内存主要包括以下几个部分: 1. **方法区(Method Area)** 2. **栈内存(Stack Memory)** 3. **堆内存(Heap Memory)** 4. **本地...

    Java之基本数据类型 Sizeof 大小

    通过分析这样的数据,我们可以更深入地理解Java内存模型,并优化我们的代码以提高效率。 总之,了解Java基本数据类型的大小对于编写高效、内存友好的代码至关重要。在没有`Sizeof`的情况下,开发者可以通过其他方式...

    Java Language Specification(Java编程规范)中英文

    引用类型则指向对象或数组的内存位置。 - **类与对象**:Java是一种面向对象的语言,类是创建对象的蓝图,对象则是类的实例。 - **包**:用作命名空间,组织类和接口。 - **访问修饰符**:public, private, ...

    java教学ppt--第2-2章_Java_语言基础

    3. **基本数据类型**:Java有八种基本数据类型,包括整型(byte、short、int、long)、浮点型(float、double)、字符型(char)和布尔型(boolean)。每种类型都有其固定的大小和取值范围。 4. **常量、变量、...

    Java使用内存的堆内存的使用.pdf

    本节主要探讨如何减少Java应用的内存使用,重点关注对象大小、对象引用和数据类型的优化。 首先,减少对象大小是降低内存消耗的有效方法。因为Java虚拟机(JVM)为每个对象分配一定的内存,包括实例变量、对象头和...

    Java面试宝典-经典

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

    java学习笔记-基础

    #### 十三、Java内存管理 Java自动管理内存,通过垃圾回收机制自动释放不再使用的对象所占内存。开发者也可以通过调用`System.gc()`方法请求垃圾回收,但实际执行时机由JVM决定。 #### 十四、Java反射与代理 反射...

    java面试题-附答案

    如果是引用类型,比较的是两个对象的内存地址,即是否指向同一个实例。 - `equals()` 方法是 Object 类的一个方法,如果没有重写,对于引用类型它默认的行为与 `==` 相同,比较对象的地址。但很多类,如 String 和 ...

Global site tag (gtag.js) - Google Analytics