decompile a .class file programmatically

2019-05-29 20:09发布

问题:

I am currently working on a project which demands me to decompile a .class file to java file programmatically. I.E. I have a program that should read a class file and decompile it and the resultant java source code is written into a file. Please help me out to do it.
EDIT: I am completely new to the world of decompilers. I have gone through a few APIs, but i don't know precisely how to use and which one to use. Any sort of help will be really appreciable
EDIT:
I tried using:

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");
}
}

But the above code simply created a file called "decompiled.java" in the scpecified directory. But the file is an empty file.

回答1:

Procyon includes a Java decompiler framework. It's written in Java, and it can be called as a library. There's not much documentation yet, but I am the author, and I can assist you if you run into trouble--just contact me on BitBucket.

A simple example of how to decompile 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
}

You can also pass a .class file path to the decompile() method instead of a class name.

If you're not using Java 7, make sure to flush/close your I/O resources manually, e.g.:

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
}


回答2:

After 5 minutes searching on Google, here's where to start:

  • De-compiling is complicated task (just like compiling). So you will likely need an external library for this taks. As with any libraries, some are good, others aren't and you must evaluate which library will fit your needs. Some libraries are http://jd.benow.ca/ (the first hit on Google) and https://github.com/alexkasko/krakatau-java (the first hit on Maven).
  • Try to evaluate which library you want to use (What are your requirements? What are the features of the library?). And then try to use the library. If you ran into any problems with a certain library, feel free to ask.

Especially https://github.com/alexkasko/krakatau-java seems to be pretty easy (from the README on GitHub):

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);