Android 中的 Java 代码编译器优化

发布于 2024-11-08 02:23:06 字数 447 浏览 2 评论 0原文

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

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”?

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

Assuming I have defined a string like this:

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

And in one of the (static) methods I call a method that receives a String as a parameter:

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

(the idea is that methodThatReceivesString() will be passed the value "ToInterBe")

My question is: Will the Java compiler optimize the code such that the compiled binary file (.jar .dex) already contain "ToInterBe"?

Or will this occur only at the application's run time?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

对你而言 2024-11-15 02:23:06

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

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

The Java compiler won't do this as it would technically change the program, since the methods involved could have side effects at runtime. But even if it would precompute the string it would still need to put the original string into the class file since it could be accessed by refection, could be relevant for a annotation or for other reasons.

I think the tool you are looking for is ProGuard. This can among many other things actually remove the string if no code refers to it anymore after all statically decidable code was precomputed.

情愿 2024-11-15 02:23:06

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

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

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


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

A Java compiler is not permitted to optimize this.

The issue is that method calls on constant objects are not defined to be constant expressions; see JLS section 15.28 for a list of the things that you can do in a constant expression. Thus, s.charAt(0) is not a constant expression even though s is a constant expression, and "we know" that its value will always be 'T'. Since it is not a constant expression, it has to be evaluated at runtime.

If your aim in doing this is to prevent the string "ToInterBe" from appearing in the classes constant pool, then you've succeeded. But that's not going to slow down a good reverse engineer by more than a couple of minutes.


(By the way, that expression probably doesn't do what you expect. The first + subexpression is an addition (not a string concatenation) because neither of the operands is a String. The result of that addition will be an int, so the entire expression will evaluate to "195InterBe" ... I think.)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文