混淆器通常只是简单地将类、方法和字段名称更改为没有意义的名称。所以,如果你有“ScoreCalculator.computeScore(Player p, Match m)”,你最终会得到“A.zk(F f, R r)”。这类似于 Uglify 或 Closure 编译器为 javascript 所做的,只是在 javascript 中它是为了减少源代码长度。
无论如何都可以理解该方法的作用,只是更难。
此外,Java 使用后期绑定(作为 DLL 或 SO 文件)。因此,不能混淆代码之外的调用(如 java.util、java.lang 等包)。此外,如果您的代码需要接收来自外部的调用(典型示例,在按钮上注册一个侦听器),则该代码不能被混淆。DLL 也是如此,您可以清楚地看到需要在 DLL 外部调用的方法的名称以及对其他 DLL 的调用。
但是,某个源代码和编译后的代码之间的映射不一定是一一对应的。旧的 C 编译器用于为给定的源指令生成相同的操作码,因此反编译器非常有效。然后 C 编译器为生成的操作代码添加了许多优化,这些优化使反编译器大多无效[1]
Java 从未在编译时实现(很多)优化,因为要在不同的平台(包括不同的 android 设备)上运行,Java 决定稍后在运行时根据运行设备的架构和硬件属性应用严重的优化(这就是“HotSpot”的主要内容[2])。
好的混淆器通常还会重新排序字节码指令,或者插入一些无用的指令,或者预先应用一些优化以使反编译器无法(或不太能够)如此轻松地导出源代码。
对于可以阅读字节码的人来说,这种技术是无用的,因为如果一个人可以阅读汇编代码,任何可能的 C 混淆都是无用的。
正如许多破解软件所展示的那样,逆向工程始终是可能的,即使使用 C 或其他语言,甚至在固件上(想想 iPhone 固件),因为运行您的代码的客户端总是不受信任的,并且总是可以被篡改。
如果你有非常关键的代码,价值很多钱的东西,别人可能会窃取,我建议在服务器端运行它,或者以某种方式在服务器端验证它。