Procyon:反编译jar的特定类

时间:2017-03-19 20:50:43

标签: java classloader decompiling

我尝试使用com.strobel.decompiler.Decompiler库中的Procyon反编译器从jar文件反编译特定类。

这是我目前的做法:

// jar file containing foo.class and bar.class
JarFile myJar = new JarFile("my.jar");
// creating decompiler settings
DecompilerSettings settings = new DecompilerSettings();
// set type loader to jar file
settings.setTypeLoader(new JarTypeLoader(myJar));

StringWriter foo = new StringWriter();
Decompiler.decompile("com.myjar.foo", new PlainTextOutput(foo), settings);
System.out.print(foo.toString());

但这只会打印:!!! ERROR: Failed to load class com.myjar.foo.

我很确定我错过了从my.jar加载课程的课程。 (认为​​这可以通过设置类型加载器来完成。)

实际问题:如何使用procyon反编译器从jar文件中反编译特定的类? (我的方法中我做错了什么?)

Greets,NopMind。

2 个答案:

答案 0 :(得分:1)

答案很简单:类名称空间不以.为前缀,而是以/为前缀。

所以只需替换Decompiler.decompile("com/myjar/foo", ...)即可。遗憾

答案 1 :(得分:0)

你可以哄骗Procyon对类名更宽容。您所要做的就是将“主要”类型加载器包装在InputTypeLoader

settings.setTypeLoader(new InputTypeLoader(new JarTypeLoader(myJar)));

InputTypeLoader将首先尝试使用主类型加载器查找类,如果找不到匹配项,它将尝试“按下”类名。它由命令行反编译器使用,用户可以尝试使用其他表单,例如.而不是/$。例如,如果存在类com/jar/Foo,并且用户尝试反编译com.jar.Foo,则应该能够解决该问题。它也适用于内部类,例如,com.jar.Foo.Bar可用于定位com/jar/Foo$Bar。是否要使用此功能取决于您。

我确实为您提供了建议:您可能不希望使用JarTypeLoader作为主要类型加载器。如果你这样做,Procyon只会 搜索特定jar中的类。这可能声音就像你想要的那样,但它可能不是。

请参阅,有一些优化,Procyon只有在它可以解析和分析类的依赖关系时才能执行。例如,当它反编译一个方法调用时,Procyon最初会在每个参数前面插入强制转换,这些参数不会完全匹配目标方法上的参数类型。为了正确性,必须这样做,因为该方法可能有重载,并且删除那些强制转换可能会导致调用绑定错误的方法。 然而,如果Procyon可以找到声明方法的类,它可以找到它的所有祖先类,那么它可以找出哪些转换可以安全删除,同时仍然绑定正确的方法。然后删除那些冗余的转换,从而产生更清晰的输出。这只是一个例子 - 还有其他一些例子。

以下是我建议使用的内容:

settings.setTypeLoader(
    new InputTypeLoader(                // allow more relaxed type names
        new CompositeTypeLoader(
            new JarTypeLoader(myJar),   // search your specific jar first
            new ClasspathTypeLoader()   // fall back to your classpath
        )
    )
);

这将使Procyon有机会搜索JRE中的依赖项以及恰好位于类路径中的任何其他位置。