最终静态与最终非静态字段和JVM优化

时间:2015-09-11 08:18:18

标签: java optimization static jvm final

我很好奇JVM如何处理static final字段。我看到了一个类似的问题here,但这不是我想要的。让我们考虑这样的例子:

public class TestClassX {
   public final int CODE_A = 132;
   public final int CODE_B = 948;
   public final int CODE_C = 288;
   // some other code
}

public class TestClassY {
   public static final int CODE_A = 132;
   public static final int CODE_B = 948;
   public static final int CODE_C = 288;
   // some other code
}

TestClassX字段中,由于它们是final且无法修改,因此在TestClassX类的所有实例中具有相同的值。当然我不能写TestClassX.CODE_A,但我可以说,这些值实际上对所有实例都是通用的 - 我确信,每个实例都有CODE_A字段,其值为{{1} }。

132我可以使用语法TestClassY,但初看起来对于看到"的开发人员来说更容易,但这些值对所有人来说都很常见实例"

我的主要问题: 我想JVM,在TestClassY.CODE_A的情况下,每次创建新实例时都不会为TestClassX字段使用任何额外的内存。可以? JVM是否在这种情况下进行任何优化以及它是什么样的优化?

额外的问题1)我也确定我在这里遗漏了一些非常重要的东西,这是我怀疑的原因。那是什么?

额外问题2)顺便说一句。如何在JVM优化之后查看我的Java源代码的样子(以便将来可以使用;))?有没有IDE支持这样的功能?例如IntelliJ?我想简单地看看JVM如何处理我的finalTestClassX

2 个答案:

答案 0 :(得分:8)

  • 实例中始终存在非静态字段。它们不会节省内存。
  • 通常,JVM不会优化非静态字段。即使它们是最终的,它们仍然可以使用反射或反序列化设置为不同的值。
  • 有一个实验性VM选项-XX:+TrustFinalNonStaticFields(默认情况下已关闭),它告诉JVM优化对这些字段的访问,即将它们视为常量并消除字段负载。
  • 有一个-XX:+PrintAssembly VM选项可以转储JIT编译的代码。

答案 1 :(得分:1)

对于问题的第一部分,也许this answer可以为您提供帮助。

对于第二部分,您可以通过在运行/编译代码时添加-XX:+PrintOptoAssembly标志来查看生成的程序集(如this answer中所述)。

我还应该补充一下,给你的汇编代码不是jvm生成的真实操作码,但代码需要在你的下运行 实际的架构。

希望这有帮助!