【问题标题】:decompile a .class file programmatically以编程方式反编译 .class 文件
【发布时间】:2014-06-06 17:27:32
【问题描述】:

我目前正在从事一个项目,该项目要求我以编程方式将 .class 文件反编译为 java 文件。 IE。我有一个程序应该读取一个类文件并对其进行反编译,然后将生成的 java 源代码写入一个文件。请帮我做。
编辑: 我对反编译器的世界完全陌生。我已经使用了一些 API,但我不知道如何使用以及使用哪一个。任何形式的帮助都会非常显着
编辑:
我尝试使用:

import com.strobel.decompiler.*;
import java.io.*;
public class JavaDecode {
public static void main(String[] args)throws Exception {
decompileee();
}

private static void decompileee()throws Exception
{
final DecompilerSettings settings = DecompilerSettings.javaDefaults();
final FileOutputStream stream = new FileOutputStream("C:/jp/decompiled.java");
final OutputStreamWriter writer = new OutputStreamWriter(stream); 
Decompiler.decompile("C:/jp/X.class",
new PlainTextOutput(writer),
settings
);
System.out.println("Success");
}
}

但上面的代码只是在指定目录下创建了一个名为“decompiled.java”的文件。但该文件是一个空文件。

【问题讨论】:

  • 没有足够的信息让我们能够为您提供帮助。你试过什么程序?你是如何尝试的?你期待什么结果?你得到了什么结果?
  • 这绝非易事——您应该找到一个现有的开源反编译器并使用代码。

标签: java decompiler


【解决方案1】:

Procyon 包含一个 Java 反编译器框架。它是用 Java 编写的,可以称为库。目前还没有太多文档,但我是作者,如果您遇到问题,我可以为您提供帮助——请在 BitBucket 上与我联系。

如何反编译java.lang.String的简单例子:

final DecompilerSettings settings = DecompilerSettings.javaDefaults();

try (final FileOutputStream stream = new FileOutputStream("path/to/file");
     final OutputStreamWriter writer = new OutputStreamWriter(stream)) {

    Decompiler.decompile(
        "java.lang.String",
        new PlainTextOutput(writer),
        settings
    );
}
catch (final IOException e) {
    // handle error
}

您还可以将.class 文件路径传递给decompile() 方法而不是类名。

如果您不使用 Java 7,请确保手动刷新/关闭您的 I/O 资源,例如:

try {
    final FileOutputStream stream = new FileOutputStream("path/to/file");

    try {
        final OutputStreamWriter writer = new OutputStreamWriter(stream);

        try {
            Decompiler.decompile(
                "java.lang.String",
                new PlainTextOutput(writer),
                DecompilerSettings.javaDefaults()
            );
        }
        finally {
            writer.close();
        }
    }
    finally {
        stream.close();
    }
}
catch (final IOException e) {
    // handle error
}

【讨论】:

  • 我使用了你提供的代码。我使用的确切代码在这个问题的编辑部分。但是代码只是在指定目录中生成一个空文件。任何帮助都将是可观的。
  • 你写的代码不一样。我的代码在try 资源语句中声明了streamwriter,这意味着close() 被调用,这会刷新缓冲区。尝试关闭您的作家并手动流式传输。
  • 当我尝试完全按照您给出的代码使用时,我收到一个错误:-source 1.6 不支持 try-with-resources(使用 -source 7 或更高版本来启用 try-with-资源)
  • 我编辑了我的答案,向您展示如何手动关闭资源。
  • 这对我帮助很大。谢谢。
【解决方案2】:

在 Google 上搜索 5 分钟后,从这里开始:

  • 反编译是一项复杂的任务(就像编译一样)。因此,您可能需要一个外部库来执行此任务。与任何库一样,有些是好的,有些则不是,您必须评估哪个库适合您的需求。一些库是http://jd.benow.ca/(谷歌第一击) 和https://github.com/alexkasko/krakatau-java(Maven 上的第一次点击)。
  • 尝试评估您要使用的库(您的要求是什么?库的功能是什么?)。然后尝试使用该库。如果您在使用某个库时遇到任何问题,请随时提出。

尤其是https://github.com/alexkasko/krakatau-java 似乎很简单(来自 GitHub 上的 README):

List<String> classes = Arrays.asList("foo.bar.Baz1", "foo.bar.Baz2")
List<File> classpath = ...
File outputDir = new File("out");
KrakatauLibrary krakatau = new KrakatauLibrary().
krakatau.decompile(classpath, classes, outputDir);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-08-05
    • 1970-01-01
    • 2015-03-09
    • 2011-01-20
    • 2013-09-01
    • 2012-06-13
    • 2015-01-05
    • 2016-07-09
    相关资源
    最近更新 更多