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