Java编译器不';t优化出静态最终字符串。为什么?

Java编译器不';t优化出静态最终字符串。为什么?,java,android,proguard,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文件(通过Proguard导出时)中完全删除“DEBUG\u VER”字符串,但

我的应用程序中有以下代码:

  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文件(通过Proguard导出时)中完全删除
“DEBUG\u VER”
字符串,但当我检查.apk文件时,我看到了其中的“DEBUG\u VER”字符串


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

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


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

编译Java字节码不会进行优化(除了极少数例外)

许多书为了简化而声明,“编译”阶段是优化发生的时候,但这是错误的。当优化真正发生时,字节码文件由JVM处理。因此,为了解决这个问题:优化可能发生在将字节码编译为机器本机代码时,这是由JVM工具完成的

有时根本没有优化(JVM在解释模式下工作)。有时JIT(实时编译器)会进行一些优化。有时,自适应优化器负责优化(不仅优化,而且在需要执行额外操作的情况下分析代码执行)

最后,您的文件没有问题。这就是java世界的工作方式


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

根据您发布的内容,
DEBUG
是真的,所以
REL
是假的,所以
(REL)?“发布版本”:“调试版本”
应生成“调试版本”

这正是您所观察到的,因此如果您希望看到“RELEASE\u VER”,则应设置:

public static final boolean DEBUG = false;

试试看会发生什么

好的,如果您认为不应该看到“RELEASE\u VER”,那么您可能是在为调试而编译,并且通常在调试模式下禁用此类优化。此外,即使语句被优化掉,字符串文字也可能保留在常量池中。它基本上是无害的。
DEBUG\u或发布=(REL)?“调试版本”:“调试版本”
?真正地请发布真实代码。
DEBUG\u或发布=(REL)?“DEBUG\u VER”:“DEBUG\u VER”
给出相同的字符串DEBUG\u VER,无论REL是true还是false。你注意到了吗?@Ravi Bhatt对不起,我是匆忙发布的,所以我有这个愚蠢的打字错误。现在更正。
当优化真正发生时,是字节码文件加载到JVM时
——这有点误导,也与您稍后所说的不一致。JIT不会在加载方法时对其进行优化,而是在解释模式下执行一定次数后才进行优化。(可怕的简化)做了一个小的编辑以使其更加正确,但我仍然意识到在这里进行任何简化可能会产生误导。@msi谢谢。这是有道理的,但在我的例子中,我确实希望从发布的APK中删除“DEBUG\u VER”字符串。我怎样才能做到呢?是的,不可能用几百个字来涵盖整个主题,所以我们不得不生活在简化中。但是文字上的变化使它与论点的其余部分保持一致,而且它确实触及了要点,因此+1谢谢,但根据我们的观点,这应该是可能的。这个答案不正确吗?我想他的意思是你会得到同样的结果,而不是从汇编中删除它。但如果我错了,那么答案是肯定的。即使没有预处理器,Java编译器也会(在某些情况下必须)删除明显不可访问的代码,例如,基于最终布尔值的条件为false。Java语言规范第14.21节对此进行了讨论,在实践中很容易验证。不可访问的代码被删除,但我不确定哪些代码是可访问的,但每个实例都会产生相同的最终结果。不过,我很容易就错了。谢谢,这很有效。这意味着,无论何时导出发布版本,我现在都必须记住将
boolean DEBUG
更改为false。哎哟