Fernflower 是第一个真正可用的 Java 分析反编译器,可能也是第一个用于高级编程语言的分析反编译器。
发布版本发布在 IntelliJ 社区仓库。
请将错误报告和功能请求发送到问题跟踪器(子系统 Java. Decompiler. Engine)。
Fernflower 作为 IntelliJ IDEA 的一部分打包,主要用于在调试或浏览类文件时显示 Java 代码。
Fernflower 可以通过以下命令以独立模式从命令行运行:
java -jar fernflower.jar [-<option>=<value>]* [<source>]+ <destination>
* 表示零次或多次
+ 表示一次或多次
<source>:要反编译的文件或目录。目录会被递归扫描。允许的文件扩展名为 class、zip 和 jar。前缀为 -e= 的源表示“库”文件,这些文件不会被反编译,但在分析类或方法之间的关系时会被考虑。特别是标识符重命名(参见 ren 选项)可以从外部类的信息中受益。
<destination>:放置生成的 Java 源代码的目标目录
<option>=<value>:命令行选项及其对应的值(参见下面的“命令行选项”)。
java -jar fernflower.jar -hes=0 -hdc=0 c:\Temp\binary\ -e=c:\Java\rt.jar c:\Temp\source\
java -jar fernflower.jar -dgs=1 c:\Temp\binary\library.jar c:\Temp\binary\Boot.class c:\Temp\source\
除 mpm 和 urc 外,值 1 表示选项启用,0 表示禁用。默认值(若有)在括号中给出。
通常,用户可能会更改以下选项(若有):hes, hdc, dgs, mpm, ren, urc。其余选项可以保留默认值:它们面向专业逆向工程师。
rbr (1): 隐藏桥接方法rsy (0): 隐藏合成的类成员din (1): 反编译内部类dc4 (1): 折叠 1.4 类引用das (1): 反编译断言hes (1): 隐藏空的 super 调用hdc (1): 隐藏空的默认构造函数dgs (0): 反编译泛型签名ner (1): 假设返回值不会抛出异常den (1): 反编译枚举rgn (1): 移除 getClass() 调用,当它是限定 new 语句的一部分时lit (0): 原样输出数字字面量asc (0): 将字符串和字符字面量中的非 ASCII 字符编码为 Unicode 转义bto (1): 将 int 1 解释为布尔值 true(编译器错误的解决方法)nns (0): 允许未设置合成属性(编译器错误的解决方法)uto (1): 将匿名类型视为 java.lang.Object(编译器架构缺陷的解决方法)udv (1): 从调试信息中重建变量名(如果存在)ump (1): 从相应属性中重建参数名(如果存在)rer (1): 移除空的异常范围fdi (1): 解内联 finally 结构mpm (0): 每个反编译方法允许的最大处理时间(秒)。0 表示无上限ren (0): 重命名歧义(即混淆)的类及类元素urc (-): 用户提供的实现 IIdentifierRenamer 接口的类的全名。用于确定哪些类标识符应被重命名并提供新的标识符名称(参见“重命名标识符”)inn (1): 检查 IntelliJ IDEA 特有的 @NotNull 注解,如果发现则移除插入的代码lac (0): 将 lambda 表达式反编译为匿名类nls (0): 定义输出使用的换行符。0 - '\r\n' (Windows), 1 - '\n' (Unix), 默认值依赖操作系统ind: 缩进字符串(默认是 3 个空格)crp (0): 在可能的情况下使用记录模式cps (0): 在可能的情况下使用带模式的 switchlog (INFO): 日志级别,可选值为 TRACE, INFO, WARN, ERRORiec (0): 反编译时在上下文中包含整个类路径isl (1): 内联简单的 lambda 表达式ucrc (1): 隐藏不必要的记录构造函数和 gettercci (1): 检查 try-with-resources 中的资源是否实际实现了 AutoCloseable 接口jvn (0): 用 JAD 风格名称覆盖所有局部变量名jpr (0): 在 JAD 命名中包含参数名pbo (0): 当位运算/移位运算符与算术运算符混合时添加明确的括号一些混淆器会给类及其成员元素提供简短、无意义且最重要的是模糊的名称。重新编译这样的代码会导致大量冲突。因此,建议让反编译器反过来重命名元素,确保每个标识符的唯一性。
选项 ren(即 -ren=1)激活重命名功能。默认的重命名策略如下:
org.jetbrains.java.decompiler.main.extern.IMemberIdentifierRenamer 接口的类通过 urc 选项(例如 -urc=com.example.MyRenamer)传递给 Fernflower。该类必须在应用程序类路径上可用。每个方法的含义从命名上应该很清楚:toBeRenamed 决定元素是否会被重命名,而其他三个方法分别为类、方法和字段提供新名称。
构建可执行的启动脚本:
./gradlew :installDist
启动脚本生成在 build/install/engine/bin。
Fernflower 是 IntelliJ Community 项目的一部分,欢迎贡献,发送补丁的首选方式是在 IntelliJ 社区仓库中创建拉取请求。提交补丁时,请遵循贡献指南。
Fernflower 基于 Apache License Version 2.0 许可。
Fernflower 最初由 Stiver 开发,但自 2014 年起由 JetBrains 维护。ForgeFlower 的一些补丁已合并到此仓库。Fernflower 的镜像也由 Andrew McRae 维护了很长一段时间。
正确名称是 Fernflower,而不是 FernFlower。