最好的Java 反编译工具的使用对比分析

论坛 期权论坛     
niminba   2021-5-26 12:31   846   0
<h2>前言</h2>
<p><strong>Java 反编译</strong>,一听可能觉得高深莫测,其实反编译并不是什么特别高级的操作,Java 对于 Class 字节码文件的生成有着严格的要求,如果你非常熟悉 Java 虚拟机规范,了解 Class 字节码文件中一些字节的作用,那么理解反编译的原理并不是什么问题。<br>
甚至像下面这样的 Class 文件你都能看懂一二。</p>
<p style="text-align: center"><img alt="" src="https://beijingoptbbs.oss-cn-hangzhou.aliyuncs.com/jb/2426819-a39ab928008699f958924cab9c3b36f4.jpg"></p>
<p>一般在逆向研究和代码分析中,反编译用到的比较多。不过在日常开发中,有时候只是简单的看一下所用依赖类的反编译,也是十分重要的。</p>
<p>恰好最近工作中也需要用到 <strong>Java 反编译</strong>,所以这篇文章介绍目前常见的的几种 Java 反编译工具的使用,在文章的最后也会通过<strong>编译速度</strong>、<strong>语法支持</strong>以及<strong>代码可读性</strong>三个维度,对它们<strong>进行测试</strong>,分析几款工具的<strong>优缺点</strong>。</p>
<h2>Procyon</h2>
<p>Github 链接:https://github.com/mstrobel/procyon<br>
<strong>Procyon</strong> 不仅仅是反编译工具,它其实是专注于 Java 代码的生成和分析的一整套的 Java 元编程工具。<br>
主要包括下面几个部分:</p>
<ul>
    <li>Core Framework</li>
    <li>Reflection Framework</li>
    <li>Expressions Framework</li>
    <li>Compiler Toolset (Experimental)</li>
    <li>Java Decompiler (Experimental)</li>
</ul>
<p>可以看到反编译只是 <strong>Procyon</strong> 的其中一个模块,<strong>Procyon</strong> 原来托管于 bitbucket,后来迁移到了 GitHub,根据 GitHub 的提交记录来看,也有将近两年没有更新了。不过也有依赖 <strong>Procyon</strong> 的其他的开源反编译工具如** decompiler-procyon**,更新频率还是很高的,下面也会选择这个工具进行反编译测试。</p>
<h2>使用 Procyon</h2>
<div class="blockcode">
<pre class="brush:java;">
&lt;!-- https://mvnrepository.com/artifact/org.jboss.windup.decompiler/decompiler-procyon --&gt;
&lt;dependency&gt;
    &lt;groupId&gt;org.jboss.windup.decompiler&lt;/groupId&gt;
    &lt;artifactId&gt;decompiler-procyon&lt;/artifactId&gt;
    &lt;version&gt;5.1.4.Final&lt;/version&gt;
&lt;/dependency&gt;</pre>
</div>
<p>写一个简单的反编译测试。</p>
<div class="blockcode">
<pre class="brush:java;">
package com.wdbyte.decompiler;

import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Iterator;
import java.util.List;

import org.jboss.windup.decompiler.api.DecompilationFailure;
import org.jboss.windup.decompiler.api.DecompilationListener;
import org.jboss.windup.decompiler.api.DecompilationResult;
import org.jboss.windup.decompiler.api.Decompiler;
import org.jboss.windup.decompiler.procyon.ProcyonDecompiler;

/**
* Procyon 反编译测试
*
*  @author https://github.com/niumoo
* @date 2021/05/15
*/
public class ProcyonTest {
    public static void main(String[] args) throws IOException {
        Long time = procyon("decompiler.jar", "procyon_output_jar");
        System.out.println(String.format("decompiler time: %dms", time));
    }
    public static Long procyon(String source,String targetPath) throws IOException {
        long start = System.currentTimeMillis();
        Path outDir = Paths.get(targetPath);
        Path archive = Paths.get(source);
        Decompiler dec = new ProcyonDecompiler();
        DecompilationResult res = dec.decompileArchive(archive, outDir, new DecompilationListener() {
            public void decompilationProcessComplete() {
                System.out.println("decompilationProcessComplete");
            }
            public void decompilationFailed(List&lt;String&gt; inputPath, String message) {
                System.out.println("decompilationFailed");
            }
            public void fileDecompiled(List&lt;String&gt; inputPath, String outputPath) {
            }
            public boolean isCancelled() {
                return false;
            }
        });

        if (!res.getFailures().isEmpty()) {
            StringBuilder sb = new StringBuilder();
            sb.append("Failed decompilation of " + res.getFailures().size() + " classes: ");
            Iterator failureIterator = res.getFailures().iterator();
            while (failureIterator.hasNext()) {
                DecompilationFailure dex = (DecompilationFailure)failureIterator.next();
                sb.append(System.lineSeparator() + "    ").append(dex.getMessage());
            }
            System.out.println(sb.toString());
        }
        System.out.println("Compilation results: " + res.getDecompiledFiles().size() + " succeeded, " + res.getFailures().size() + " failed.");
        dec.close();
        Long end = System.currentTimeMillis();
        return end - start;
    }
}</pre>
</div>
<p>Procyon 在反编译时会实时输出反编译文件数量的进度情况,最后还会统计反编译成功和失败的 Class 文件数量。</p>
<blockquote>
<p>....<br>
五月 15, 2021 10:58:28 下午 org.jboss.windup.decompiler.procyon.ProcyonDecompiler$3 call<br>
信息: Decompiling 650 / 783<br>
五月 15, 2021 10:58
分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:1060120
帖子:212021
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP