问:如果我加密.class文件并使用自定义的类加载器即时加载和解密文件,是否可以防止反编译?
答:防止Java字节码反编译的问题几乎与语言本身一样古老。尽管市场上有许多模糊处理工具,但是Java新手程序员仍然在考虑保护知识产权的新颖巧妙方法。在本期Java Q&A文章中,我消除了关于经常在讨论论坛中重新出现的一个想法的一些神话。
Java .class文件可以非常容易地重构为与原始文件非常相似的Java源代码,这与Java字节码的设计目标和权衡关系很大。除其他外,Java字节码旨在通过字节码解释器和JIT(即时)/ HotSpot动态编译器实现紧凑性,平台独立性,网络移动性和易于分析的目的。可以说,已编译的.class文件非常清楚地表达了程序员的意图,与原始源代码相比,它们可能更易于分析。
如果不能完全防止反编译,至少可以增加反编译的难度,可以做几件事。例如,作为编译后的步骤,您可以对.class数据进行处理,以使字节码在反编译时更难以阅读,或者更难于反编译为有效的Java代码(或两者)。诸如执行极端方法名称重载之类的技术对于前者而言效果很好,而操纵控制流以创建不可能通过Java语法表示的控件结构则对后者而言效果很好。比较成功的商业混淆器将这些技术与其他技术结合使用。
不幸的是,这两种方法实际上都必须更改JVM将运行的代码,许多用户担心(理应如此)这种转换可能会在其应用程序中添加新的错误。此外,方法和字段重命名可能导致反射调用停止工作。更改实际的类和程序包名称可能会破坏其他几种Java API(JNDI(Java命名和目录接口),URL提供程序等)。除了更改名称之外,如果更改了类字节码偏移量和源行号之间的关联,则恢复原始异常堆栈跟踪可能会变得困难。
然后可以选择混淆原始Java源代码。但是从根本上讲,这会引起一系列类似的问题。加密,而不是混淆?
也许上面的内容使您想到:“好吧,如果我不处理字节码,而是在编译后对我的所有类进行加密,然后在JVM中对其进行动态解密(可以通过自定义类加载器完成),那该怎么办?然后JVM执行我的原始字节码,却没有反编译或反向工程的功能,对吧?”
不幸的是,您既会认为自己是第一个提出此想法的人,又会认为它确实有效,这是错误的。原因与加密方案的强度无关。