Android 中的 Java 代码编译器优化



假设我定义了这样的字符串:

private final static String s = "To Be or not to be, that is the question";

在其中一个(静态)方法中,我调用了一个接收字符串作为参数的方法:

methodThatReceivesString(s.charAt(0) + s.charAt(1) + "Inter" + s.charAt(3) + s.charAt(4))

(这个想法是methodThatReceivesString()将被传递值"ToInterBe")

我的问题是:Java编译器是否会优化代码,使编译的二进制文件(.jar.dex)已经包含"ToInterBe"?

还是仅在应用程序的运行时发生?

Java 编译器不会这样做,因为它会在技术上更改程序,因为所涉及的方法可能会在运行时产生副作用。但是,即使它会预先计算字符串,它仍然需要将原始字符串放入类文件中,因为它可以通过引用访问,可能与注释或其他原因相关。

我认为您正在寻找的工具是ProGuard。如果在预先计算了所有静态可判定的代码之后,如果没有代码引用它,这实际上可以删除字符串。

不允许 Java 编译器对此进行优化。

问题在于,对常量对象的方法调用未定义为常量表达式;有关可以在常量表达式中执行的操作的列表,请参阅 JLS 第 15.28 节。 因此,即使s.charAt(0)是一个常量表达式,s也不是常量表达式,并且"我们知道"它的值将始终是'T'的。 由于它不是常量表达式,因此必须在运行时对其进行计算。

如果您这样做的目的是防止字符串"ToInterBe"出现在类常量池中,那么您已经成功了。 但这不会让一个好的逆向工程师减慢超过几分钟的速度。


(顺便说一下,该表达式可能不会达到您的预期。 第一个+子表达式是加法(不是字符串连接),因为两个操作数都不是 String。 该加法的结果将是一个int,因此整个表达式的计算结果将为"195InterBe"...我想。

最新更新