【发布时间】:2010-11-29 11:27:22
【问题描述】:
假设一个 Java 对象只占用对象引用的 8 个字节,只要它的所有成员都设置为 null 是否正确,或者成员的定义是否由于某种原因已经占用了实例中的空间?
换句话说,如果我有大量对象想要节省空间,我可以指望将未使用的成员设置为null 以减少内存占用吗?
【问题讨论】:
标签: java optimization memory
假设一个 Java 对象只占用对象引用的 8 个字节,只要它的所有成员都设置为 null 是否正确,或者成员的定义是否由于某种原因已经占用了实例中的空间?
换句话说,如果我有大量对象想要节省空间,我可以指望将未使用的成员设置为null 以减少内存占用吗?
【问题讨论】:
标签: java optimization memory
不,您在字段中存储的每个空值都需要 4 或 8 个字节(取决于它是 32 位还是 64 位系统)。如果没有存储的东西告诉它,对象怎么知道它的字段是空的?
【讨论】:
不,null 也是信息,也必须存储。
【讨论】:
对象引用本身仍会占用一些内存,因此唯一真正节省的内存将来自被引用的堆对象。
所以,如果你有
MyClass {
public Object obj;
MyClass(Object o) { obj = o; }
}
MyClass a = new MyClass( new HashMap() );
MyClass b = new MyClass( null );
a 和b 这两个对象本身占用的内存量相同(它们都持有一个引用),但是a 引用的对象obj 占用了堆上的内存,所以这个可以通过将引用设置为 null 来节省内存。
【讨论】:
Java Language Specification 和Java Virtual Machine Specification 没有说明 Java 对象在内存中的大小 - 它故意未定义,因为它取决于 JVM 的实现。这意味着您无法对 Java 对象通常使用多少内存或 Java 对象在内存中的内存布局做出任何假设。
正如其他人已经说过的:引用(变量)占用内存,无论引用是否为null。当您将成员变量设置为 null 时,您的对象不会缩小并占用更少的内存。
【讨论】:
类、对象和方法名呢?正如您可以使用 Java 反射调用、访问或实例化它们一样,名称也必须存储在某个地方,对吗?但是CMIIW。
影
【讨论】:
当一个 Java 对象的所有成员都为空时,它会消耗内存,因为 它还对标头、引用和内务管理有一些额外的内存要求。
Java对象使用的堆内存包括
原始字段的内存,取决于它们的大小。
引用字段的内存(每个 4 个字节)。
一个对象头,由几个字节的“管家”信息组成。
Java 中的对象还需要一些“管家”信息,例如记录对象的类、ID 和状态标志,例如对象当前是否可达、当前是否被同步锁定等。
Java 对象头大小在 32 位和 64 位 jvm 上有所不同。
虽然这些是主要的内存消费者,但 jvm 有时也需要额外的字段,例如用于对齐代码等。
所以这就是当你的 Java 对象的所有成员都为 null 时它会消耗内存的原因。
【讨论】: