Java编译器不会优化静态最终字符串。为什么?

时间:2012-01-29 01:03:22

标签: java android proguard

我的应用中有以下代码:

  public static final boolean DEBUG = true;
  public static final boolean REL = !DEBUG;

  private static final String DEBUG_OR_RELEASE = (REL) ? "RELEASE_VER" : "DEBUG_VER";

我认为Java编译器将从生成的.apk文件中完全消除"DEBUG_VER"字符串(当通过Proguard导出时)但是当我检查.apk文件时,我看到那里的“DEBUG_VER”字符串。

为什么呢?我错过了什么?我做错了什么?

3 个答案:

答案 0 :(得分:3)

编译为java字节码没有进行优化(除了极少数例外)。

许多书籍都说明了“编译”阶段在优化发生时的简化,但这是错误的。当优化真正发生时,是字节码文件由JVM处理。因此,为了清除:在编译字节码以加工本机代码时可能会发生优化,这是由JVM工具完成的。

有时根本没有优化(JVM在解释模式下工作)。有时JIT(Just In Time complier)会进行一些优化。有时,自适应优化器负责优化(不仅可以优化,还可以在执行其他操作时分析代码执行)。

最后,您的文件没有任何问题。这就是Java世界的运作方式。

“但为什么?” - 你可能会问。在字节码中保留这些“无用”信息的原因是因为您永远无法确定可以消除多少代码,因此不同JVM提供的优化仍然可以高效工作。最好的方法是不删除任何信息,让优化者完成他们的工作。

答案 1 :(得分:1)

即使变量设置为true,它仍然在运行。 ?:语句是可执行代码和操作代码的一部分,由于Java没有预编译器,每次编译时都会运行

Java不会自动推断和简化操作,即使逻辑上每次迭代的操作都相同。

答案 2 :(得分:1)

根据您发布的内容,DEBUG为真,因此REL为false,因此(REL) ? "RELEASE_VER" : "DEBUG_VER"应该产生“DEBUG_VER”。

这正是你所观察到的,所以如果你期望看到“RELEASE_VER”,你应该设置:

public static final boolean DEBUG = false;

试试看看会发生什么。