类设计最小化内存使用:如果对象实例变量(非基元)为null,它是否仍然使用必要的引用字节?

时间:2012-04-13 18:28:08

标签: java memory memory-management jvm

我目前正在设计一种数据结构,我试图将内存消耗降至最低。我有一些实例变量可能为null,具体取决于Trie中Node的位置。我开始沿着创建单独类的路径(一个具有实例变量而另一个没有实例变量),这样我就不会浪费大量空间和空引用...但后来我开始想知道jvm是如何工作的。如果对象引用为null或者它是否有更优化的方法来存储空引用,它是否仍然占用了整个8个字节(假设是x64 arch)?

4 个答案:

答案 0 :(得分:2)

我几乎可以肯定JVM会为null引用使用尽可能多的空间。如果你有一个带有3个参考字段的对象,并且你将中间的那个归零,我认为任何虚拟机都不能移动第3个并保存4或8个字节(然后当你改变时) null到其他东西,它将不得不再次移动东西)。如果这在技术上是可行的,那就不值得了 - 额外的计算成本和代码复杂性会杀死任何潜在的收益。此外,部分由于C遗产,在大多数机器上,与0相等的指针在非常低的水平上作为NULL工作,因此null引用具有相当明显的表示。

在Oracle / Sun JDK上,如果堆小于16 GB,则可以使用-XX:+UseCompressedOops命令行参数在64位上引用4个字节而不是8个引用(无论引用是否为{{1}或不)。

答案 1 :(得分:1)

答案是肯定仍然使用必要的字节。 在Java中,null只是引用可以具有的值。这意味着参考没有任何意义。在这种情况下,您仍然占用参考空间。这是32位系统上的4个字节或64位系统上的8个字节。

请参阅Does null variable require space in memory

答案 2 :(得分:0)

类和超类也使用一些字节。

如果你真的想避免大部分内存使用,我建议使用 FlyWeight 模式

(想法:重用相同的不可变对象;让工厂创建和缓存它们。)

你的代码变得有点复杂,这很糟糕。但是你可以节省很多钱。


另一种选择是处理更简单的类型(而不是对象)。 它不太实用,你必须在数据外部做所有事情...... 所以我更喜欢FlyWeight。

答案 3 :(得分:0)

我们可以应用简单的数学:假设你有一个类型int的字段的对象,在任何架构上都是4个字节,可以是未定义的(它取决于用例该字段必须采用的值)你可以理解它是未定义的)。现在,如果已定义,则使用4个字节。如果未定义,则浪费4个字节。

假设您将其包装到对象中。现在,如果定义了字段,它将使用4或8个字节(取决于JVM位数和指针压缩打开或关闭-XX:+UseCompressedOops)作为指针。具有单个4字节字段的对象将消耗16个字节而不管位数如何(对象将在32位和64位Java运行时上占用16个字节,因为它包含8或12个字节的对象标头和4个字节的值,并且使用的内存已对齐最近的8个字节)。

总结一下,如果你坚持使用原语,你将使用4个字节。如果将单个int包装到一个对象中,如果该字段具有值,则将使用20或24个字节;如果值为null,则为4或8个字节。