如何查找对象分配的总内存

6

可能重复:
在Java中,确定对象的大小最好的方法是什么?

如果我们在一个类中创建实例变量和实例方法,那么如何找出为该类的每个对象分配的总内存,例如下面的示例,我认为它是变量 (a,b) 的大小和方法区域大小(display)之和。这是真的吗?那么写在类内的主要方法区域呢?

例如:

class A {  
    int a;
    float b;
    void display()
    {  
       ---
    }

    public static void main(String a[])
    { 
        A obj=new A();
    }
}
2个回答

9
简单的回答是,除非你知道这是一个问题,否则你不需要知道。
更详细的回答是,它将使用对象头的大约16个字节,每个字段4个字节(并将总和舍入为8个字节边界),即24个字节。
局部变量例如引用在堆栈上分配,并且通常不计算在内。
你通常不会关心大小的原因是,1 MB的价值约为你2秒钟的时间(比较内存的零售价格与最低工资)。这意味着你提问所花费的时间远比你可能节省的内存价值更高(在这种情况下)。
[4 GB模块的成本为18英镑,最低工资为8.5英镑,因此1 GB的价值约为0.5小时。1 MB的价值约为2秒钟。]
换句话说,如果一个简单的更改不能为你节省1 MB的内存,而你有更好的用途,那么你可能在浪费时间。
移动设备也是如此,但程度要小一些(内存成本更高,如果部署到数千台设备上,保存几百字节的总成本可能很重要)
这样做的结果是,你写long而不是int或者double而不是float(它们都有一个额外的字符)所需的时间可能比额外使用的内存值得多了。但是,我仍然建议几乎总是使用double代替float,并且常常使用long代替int,因为如果它可以节省一个bug,那么你需要键入的额外字符将会弥补更多。
衡量一个对象使用多少空间(或创建一个对象使用多少内存)最简单的方法是关闭TLAB-XX:-UseTLAB,并测量在创建对象之前和之后的内存量,即Runtime.totalMemory - freeMemory。
然而,在我认为它是个问题之前,我更喜欢等待数据结构出现在像YourKit(VisualVM是免费的)这样的分析器中。

1
你可以使用 java.lang.instrumentation 包: http://java.sun.com/j2se/1.5.0/docs/api/java/lang/instrument/Instrumentation.html 编译并将此类放入 JAR 包中:
import java.lang.instrument.Instrumentation;

public class ObjectSizeFetcher {
    private static Instrumentation instrumentation;

    public static void premain(String args, Instrumentation inst) {
        instrumentation = inst;
    }

    public static long getObjectSize(Object o) {
        return instrumentation.getObjectSize(o);
    }
}

请在您的MANIFEST.MF中添加以下内容:
Premain-Class: ObjectSizeFetcher

使用 getObjectSize():
public class C {
    private int x;
    private int y;

    public static void main(String [] args) {
        System.out.println(ObjectSizeFetcher.getObjectSize(new C()));
    }
}

使用以下命令调用文件:java -javaagent:ObjectSizeFetcherAgent.jar C


1
或者你可以使用内存分析器,例如VisualVM来告诉你每个对象使用了多少内存。 ;) - Peter Lawrey
向 http://stackoverflow.com/users/5438/stefan-karlsson 致敬,感谢他在 https://dev59.com/TnVD5IYBdhLWcg3wNIzc#52682 上的回答。 - Kirby

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接