我尝试使用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。
答案 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中的依赖项以及恰好位于类路径中的任何其他位置。