我有一个应用程序,读取一个CSV文件与成堆的数据行。我根据数据类型向用户提供了行数的摘要,但我想确保不会读入太多行数据而导致OutOfMemoryErrors。每一行转换成一个对象。有没有一种简单的方法以编程方式找出该对象的大小?是否有一个引用定义了一个VM的基本类型和对象引用有多大?

现在,我有代码说读取多达32,000行,但我还希望有代码说读取尽可能多的行,直到我使用了32MB的内存。也许这是另一个问题,但我还是想知道。


当前回答

许多其他答案提供了浅的大小——例如,没有任何键或值的HashMap的大小,这可能不是您想要的。

jamm项目使用上面的java.lang.instrumentation包,但是遍历树,因此可以为您提供深层内存使用。

new MemoryMeter().measureDeep(myHashMap);

https://github.com/jbellis/jamm

要使用MemoryMeter,请使用“-javaagent:/jam .jar”启动JVM

其他回答

可以使用java.lang.instrument包。

编译并将这个类放入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);
    }
}

将以下内容添加到您的清单中。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

我偶然发现了一个java类 "jdk.nashorn.internal.ir.debug. objectsizecalculator ",已经在jdk中, 这很容易使用,似乎对确定物体的大小非常有用。

System.out.println(ObjectSizeCalculator.getObjectSize(new gnu.trove.map.hash.TObjectIntHashMap<String>(12000, 0.6f, -1)));
System.out.println(ObjectSizeCalculator.getObjectSize(new HashMap<String, Integer>(100000)));
System.out.println(ObjectSizeCalculator.getObjectSize(3));
System.out.println(ObjectSizeCalculator.getObjectSize(new int[]{1, 2, 3, 4, 5, 6, 7 }));
System.out.println(ObjectSizeCalculator.getObjectSize(new int[100]));

结果:

164192
48
16
48
416

没有方法调用,如果这是你想要的。只要稍加研究,我想你就可以自己写了。一个特定的实例具有一个固定的大小,该大小来自引用和原语值的数量以及实例簿记数据。您可以简单地遍历对象图。行类型变化越少,越容易。

如果这太慢或者麻烦太多,总有好的老式的行计数经验法则。

几年前,Javaworld有一篇关于确定组合和潜在嵌套Java对象大小的文章,他们基本上介绍了如何在Java中创建sizeof()实现。这种方法基本上建立在其他工作的基础上,在这些工作中,人们通过实验确定了原语和典型Java对象的大小,然后将该知识应用于递归地遍历对象图以计算总大小的方法。

它总是比原生C实现更不准确,这仅仅是因为类背后发生的事情,但它应该是一个很好的指示器。

另外一个SourceForge项目被适当地称为sizeof,它提供了一个带有sizeof()实现的Java5库。

附注:不要使用序列化方法,序列化对象的大小和它在运行时所消耗的内存量之间没有相关性。

许多其他答案提供了浅的大小——例如,没有任何键或值的HashMap的大小,这可能不是您想要的。

jamm项目使用上面的java.lang.instrumentation包,但是遍历树,因此可以为您提供深层内存使用。

new MemoryMeter().measureDeep(myHashMap);

https://github.com/jbellis/jamm

要使用MemoryMeter,请使用“-javaagent:/jam .jar”启动JVM