【发布时间】:2011-02-23 07:00:42
【问题描述】:
我知道 Java 的实现会尽其所能向开发人员隐藏这些信息,但我正在构建一个不依赖于第三方库的内存绑定算法,因此这些信息会派上用场。
特别是,我将许多大型int[] 数组分配为实例变量。我将很快研究更紧凑的表示,但现在我想知道一个普通数组使用了多少空间。
【问题讨论】:
标签: java memory memory-management
我知道 Java 的实现会尽其所能向开发人员隐藏这些信息,但我正在构建一个不依赖于第三方库的内存绑定算法,因此这些信息会派上用场。
特别是,我将许多大型int[] 数组分配为实例变量。我将很快研究更紧凑的表示,但现在我想知道一个普通数组使用了多少空间。
【问题讨论】:
标签: java memory memory-management
好吧,int 字段可能由于填充而最终占用超过 4 个字节......但基本上它是 4 个字节(32 位)。至于它是否确实占用超过 4 个字节,您必须进行试验才能找到答案。对于对象中的字段,这相当容易做到;对于基于堆栈的 int 值更难。
例如,int 的大数组总是会占用大约 4 倍的长度(+ 少量的长度开销等)。我不相信元素之间会应用填充——尽管验证这一点相对容易。 Runtime.totalMemory() - Runtime.freeMemory() 返回的值只应谨慎使用,但如果您在一次运行中分配 100 万个整数的数组,然后在另一次中分配 200 万个整数,然后是 300 万个整数,等等,应该相当清楚发生了什么。
示例代码:
public class Test {
public static void main(String[] args) {
int size = Integer.parseInt(args[0]);
long before = getUsedMemory();
int[] array = new int[size];
long after = getUsedMemory();
long difference = after - before;
System.out.println("Total difference: " + (after - before));
System.out.println("Per element: " + ((double) difference) / size);
System.out.println(array); // Make sure the array isn't GC'd early
}
private static long getUsedMemory() {
Runtime rt = Runtime.getRuntime();
return rt.totalMemory() - rt.freeMemory();
}
}
在我的机器上,尝试使用 100000、2000000 和 3000000 会为所有运行提供“4*size + 16”字节。
【讨论】:
只是一个int 本身?这可能取决于它与什么相邻,等等。或者您的意思是int 的数组?我有 99% 的把握在所有合理的 JVM 实现中都会占用 4 个字节(加上数组对象本身的一些固定开销)。
long before = Runtime.getRuntime().freeMemory();
int foo[] = new int[123456];
System.out.println("Approximate bytes per int: "
+ (before - Runtime.getRuntime().freeMemory())/(float)123456);
报告:
每个 int 的近似字节数:4.0001945
【讨论】:
【讨论】:
int 中,它会以某种方式抱怨或行为不端。但是在它内部可以以任何可能的方式实现,即使为每个 int 分配 1 Gb 并且只使用 4 个字节。虽然这肯定很荒谬,但有可能:)