Fernflower

返回 JDK 工具 | → 编译与运行

Fernflower 是 JetBrains 开发的分析型 Java 反编译器,内置于 IntelliJ IDEA。它将 .class 字节码还原为可读的 Java 源码,是目前还原质量最高的开源 Java 反编译器之一。


反编译流程

.class 字节码
    │
    ▼ 字节码解析(结构分析)
  指令序列 + 常量池
    │
    ▼ 控制流重建(基于 CFG)  ← 参见 [[cfg|CFG]]
  结构化控制流(if/while/for/switch)
    │
    ▼ 数据流分析
  变量类型推断、表达式合并
    │
    ▼ 去糖还原
  还原 lambda、try-with-resources、增强 for 等
    │
    ▼ 源码生成
  .java 文件

Fernflower 属于结构化反编译器(Structuring Decompiler),核心难点在于从非结构化的字节码跳转重建出结构化的控制流(if/else/loop)。


命令行使用

Fernflower 以 JAR 形式发布,可独立运行:

# 从 IDEA 安装目录找到 fernflower.jar
# Linux/Mac: $IDEA_HOME/plugins/java-decompiler/lib/java-decompiler.jar
# Windows:   %IDEA_HOME%\plugins\java-decompiler\lib\java-decompiler.jar
 
# 反编译单个 class 文件,输出到 out/ 目录
java -jar fernflower.jar Hello.class out/
 
# 反编译整个 jar 包(输出同样为 jar,内含 .java 源文件)
java -jar fernflower.jar app.jar out/
 
# 指定多个来源
java -jar fernflower.jar Foo.class Bar.class out/

常用选项

选项以 -key=value 形式传入,放在源文件路径之前

选项默认说明
-hes=11隐藏空的 super 调用
-hdc=11隐藏默认构造器
-dgs=00去糖 String switch(转为等价 if-else)
-nls=00统一换行符(0=系统,1=\n
-den=11去糖枚举
-rbr=11移除空的 try-catch 块
-bsm=11反编译 bootstrap 方法(lambda)
-udv=11还原调试变量名(需 .class 含调试信息)
-rer=11还原 record 类
-log=INFOINFO日志级别(TRACE/INFO/WARN/ERROR)
# 示例:禁止隐藏默认构造器,开启 String switch 去糖
java -jar fernflower.jar -hdc=0 -dgs=1 app.jar out/

在 IntelliJ IDEA 中使用

IDEA 已内置 Fernflower,无需手动调用:

  1. 在项目/依赖中打开任意 .class 文件
  2. IDEA 自动调用 Fernflower 并展示反编译结果
  3. 右键 → Decompile to source 可保存为 .java

.class 编译时带有 -g 调试信息(参见 javac),还原的变量名会更接近原始代码。


局限性

场景说明
混淆代码变量/方法名已被替换为无意义字符,结构可还原但语义难懂
复杂控制流深层嵌套或 goto 密集的字节码可能还原为 goto 语句
运行时生成类动态生成的类(如 CGLIB 代理)结构混乱,可读性差
版本差异高版本字节码特性(如 sealed class)在旧版 Fernflower 中支持有限

与其他反编译器对比

工具优势劣势
Fernflower还原质量高、支持新语法速度稍慢
CFR速度快、命令行友好部分语法还原不如 Fernflower
Procyon早期还原质量好更新较少
JAD老工具,速度快不支持 Java 5+ 新特性

相关链接

  • 编译与运行.class 文件的编译来源
  • javac — 编译选项(-g 保留调试信息影响反编译质量)
  • CFG — Fernflower 内部重建控制流的理论基础
  • JVM — 字节码格式与结构