【问题标题】:Java Code Compiler Optimization in AndroidAndroid 中的 Java 代码编译器优化
【发布时间】:2011-08-27 16:08:34
【问题描述】:

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

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 android optimization compiler-optimization


    【解决方案1】:

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

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

    【讨论】:

      【解决方案2】:

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

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

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


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

      【讨论】:

      • 接受+1。为什么只有2分钟?
      • @ef2011 - 因为他很擅长他的工作并且以前见过这个技巧。 (好吧……也许 10 或 20 分钟)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-02-14
      • 1970-01-01
      • 2011-08-24
      • 1970-01-01
      相关资源
      最近更新 更多