【Java】反编译工具 - procyon decompiler

5,673 阅读3分钟

对比和使用了这么多反编译工具,目前觉得 procyon-decompiler 最好用。

官方资料

特点

Procyon Decompiler 尤其擅长反编译以下工作:

  1. 枚举类声明。
  2. 枚举和字符串的 switch 声明。
  3. 内部类
  4. 注解
  5. Lambda 表达式

输出

Procyon Decompiler 支持三种反编译输出格式:

  • Java 代码
  • 字节码(相当于 javap)
  • 字节码抽象语法树,介于 Java 代码与字节码的中间表示。

使用

运行环境

  • JDK1.7 及以上。

语法

java -jar procyon-decompiler.jar <main class> [options] <type names or class/jar files>

示例:

PS C:/> java -jar "C:\Program Files\Jars\procyon-decompiler.jar" java.lang.Object
//
// Decompiled by Procyon v0.6-prerelease
//

package java.lang;

import jdk.internal.HotSpotIntrinsicCandidate;

public class Object
{
    private static native void registerNatives();

    @HotSpotIntrinsicCandidate
    public Object() {}

    @HotSpotIntrinsicCandidate
    public final native Class<?> getClass();

    @HotSpotIntrinsicCandidate
    public native int hashCode();

    public boolean equals(final Object o) {return this == o;}

    @HotSpotIntrinsicCandidate
    protected native Object clone() throws CloneNotSupportedException;

    public String toString() {
        return this.getClass().getName() + "@" + Integer.toHexString(this.hashCode());
    }

    @HotSpotIntrinsicCandidate
    public final native void notify();

    @HotSpotIntrinsicCandidate
    public final native void notifyAll();

    public final native void wait(final long p0) throws InterruptedException;

    public final void wait(long n, final int n2) throws InterruptedException {
        if (n < 0L) {
            throw new IllegalArgumentException("timeout value is negative");
        }
        if (n2 < 0 || n2 > 999999) {
            throw new IllegalArgumentException("nanosecond timeout value out of range");
        }
        if (n2 > 0) {
            ++n;
        }
        this.wait(n);
    }

    public final void wait() throws InterruptedException {this.wait(0L);}

    @Deprecated(since = "9")
    protected void finalize() throws Throwable {}

    static {registerNatives();}
}

参数

帮助java -jar procyon-decompiler.jar -?

optfull option name描述
-b--bytecode-ast输出字节码抽象语法树
-ci--collapse-import合并 import 列表中同一个包的类
--compiler-target n指定反编译的目标 JDK 版本,如 89
-cp--constant-pool输出常量池,仅 -r 时可用,-v 时自动启用
-dl--debug-line-numbers【仍不清楚】
--disable-foreach禁用 for each 循环
-eml--eager-method-loading【仍不清楚】
-ent--exclude-nested不输出内部类
-eta--explicit-type-arguments输出泛型方法的完整参数
-fsb--flatten-switch-blocks去掉 switch 判断中的括号
-fq--force-qualified-references强制输出所有类型的完整全限定名
-lc--light输出控制台定义的白色背景颜色
-lv--local-variables输出本地变量表,仅 -r 时可用,-v 时自动启用
-ll--log-level n设置日志级别(0-3),0 为不显示,默认 0
-ln--with-line-numbers输出行号
-mv--merge-variables合并变量减少声明次数,但可读性会变差
-o--output-directory dir将反编译结果输出到文件夹中
-r--raw-bytecode输出原始字节码,通过 -cp-lv-ta-v 设置输出级别
-ec--retain-explicit-casts保留没有必要的类型转换
-ps--retain-pointless-switches【仍不清楚】
-ss--show-synthetic保留编译器生成的代码,如默认构造方法
-sm--simplify-member-references简化指定类型的成员引用
-sl--stretch-lines【仍不清楚】
--text-block-line-min【仍不清楚】
-ta--type-attributes详细输出对象类型的属性,仅 -r 时可用,-v 时自动启用
--unicode以 Unicode 格式输出
-u--unoptimized显示优化输出之前的代码
-v--verbose详细模式,输出所有信息
--version输出 procyon 的版本

设置为 IDEA 工具

Setting > Tools >> External Tools >>> + 即可设置为 IDEA 工具,在 Project 的文件上右键可以选择对目标文件执行该命令。

image.png

image.png

设置:

  • Program:设置为 Java 程序的路径。

  • Arguments:设置 Java 的参数,基础参数为 -jar <procyon-decompiler.jar filepath> $FilePath$

    -jar 后接 procyon 的 jar 包路径。$FilePath$ 是 IDEA 注入的变量,有非常多,点击 + 号可以选择自己想用的变量。后面可以接各种 procyon 的参数,根据自己想要的输出形式设置。

  • Working derectory:没用,因为 procyon 不会默认输出文件。

如果希望输出的样式多一点,可以设置成多个工具,如:

image.png