有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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”

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


共 (2) 个答案

  1. # 1 楼答案

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

    问题在于,对常量对象的方法调用没有定义为常量表达式;请参阅JLSsection 15.28,了解在常量表达式中可以执行的操作列表。因此,s.charAt(0)不是一个常量表达式,即使s是一个常量表达式,“我们知道”它的值将始终是'T'。因为它不是一个常量表达式,所以必须在运行时对其求值

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


    (顺便说一句,这个表达式可能没有达到您预期的效果。第一个+子表达式是一个加法(不是字符串串联),因为两个操作数都不是字符串。这个加法的结果将是一个int,所以整个表达式的计算结果将是"195InterBe"。。。我想。)

  2. # 2 楼答案

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

    我想你要找的工具是ProGuard。如果在所有静态可判定代码被预计算之后,没有代码再引用字符串,那么这实际上可以删除字符串