【发布时间】:2021-09-11 05:13:47
【问题描述】:
在优化我的代码时,我正在尝试更多地了解 JVM,并且很好奇它是否(或更具体地以哪些方式)优化了未使用的字段?
我假设如果您在一个类中有一个从未写入或读取过的字段,则当代码运行时,该字段将不存在于该类中。假设您有一个如下所示的课程:
public class Foo {
public final int A;
public final float B;
private final long[] C = new long[512];
}
并且您只使用了变量 A 和 B,那么您可能会看到初始化、维护和释放变量 C 对于本质上是垃圾数据的东西是多么浪费时间。首先,我假设 JVM 会发现这一点是正确的吗?
现在我的第二个也是更重要的例子是 JVM 是否在这里考虑继承?比如说 Foo 看起来更像这样:
public class Foo {
public final int A;
public final float B;
private final long[] C = new long[512];
public long get(int i) {
return C[i];
}
}
然后我假设这个类将存储在内存中的某个地方,有点像:
[答:4 | B:4 | C:1024]
所以如果我有第二堂课看起来像这样:
public class Bar extends Foo {
public final long D;
@Override public long get(int i) {
return i * D;
}
}
然后突然这意味着字段 C 从未使用过,因此内存中的 Bar 实例将如下所示:
[答:4 | B:4 | C:1024 | D:8 ] 或 [ A:4 | B:4 | D:8 ]
【问题讨论】:
-
JIT 可能。但在现代系统中,担心如此微小的优化几乎肯定是毫无意义的。你意识到计算机现在有千兆字节的内存,对吧?在编写 Java 时,您很幸运拥有 32 兆字节。我想我的电脑当时有 5 兆字节。担心单个
int的空间仍然毫无意义。也许在 Atari 2600 时代,这是个问题。 -
其实我觉得大部分情况下JIT都做不到。问题在于,如果它确实优化了它们,然后证明它们是必需的(用于调试,在新的子类中等),JVM 无法找到/更新对象节点以添加空间来存储字段。
-
@ElliottFrisch 是的,但是如果您正在处理一个 65536 字节长的数组,那感觉会浪费很多内存。
-
“但是如果你正在处理一个 65536 字节长的数组呢?”。在Java中,数组是独立的堆节点,所以字段只需要空间来引用数组;即 4 或 8 个字节。如果不需要数组,则字段不应该被初始化......由该字段所属的类。 (理论上,冗余分配可以被优化掉,但我怀疑它会被实现......原因与我之前的评论类似。)
-
因此,在您的示例中,
C字段使用的内存是 4 或 8 个字节,而不是 1024。
标签: java optimization memory jvm unused-variables