Android中的Java代码编译器优化

时间:2011-05-18 00:21:20

标签: java android optimization compiler-optimization

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

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

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

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

(想法是methodThatReceivesString()将传递值“ToInterBe”)

我的问题是:Java编译器是否会优化代码,以便编译后的二进制文件(。jar .dex)已包含“ToInterBe”?

或者这只会在应用程序的运行时发生吗?

2 个答案:

答案 0 :(得分:2)

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

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

答案 1 :(得分:1)

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

问题是对常量对象的方法调用未定义为常量表达式;请参阅JLS section 15.28以获取可在常量表达式中执行的操作的列表。因此,s.charAt(0)不是常量表达式,即使s是常量表达式,并且“我们知道”其值始终为'T'。由于它不是常量表达式,因此必须在运行时进行评估。

如果你这样做的目的是阻止字符串"ToInterBe"出现在类常量池中,那么你就成功了。但这不会让一个好的逆向工程师放慢几分钟。


(顺便说一句,那个表达式可能不会达到预期的效果。第一个+子表达式是一个加法(不是字符串连接),因为这两个操作数都不是String。这个加法的结果将是int,因此整个表达式将评估为"195InterBe" ...我认为。)