我正在尋找一種方法來獲取jar文件中所有類的方法存根的列表。 我不知道從哪裏開始...我可以使用Reflection還是Javassist或其他我還沒聽說過的工具!? 至少它可能是解壓罐,反編譯類文件和掃描線解析器的方法,但我認爲這是最骯髒的方式;-)Java:簡單的方法來獲取JAR文件中類文件的方法存根?反射?
任何想法?
親切的問候
我正在尋找一種方法來獲取jar文件中所有類的方法存根的列表。 我不知道從哪裏開始...我可以使用Reflection還是Javassist或其他我還沒聽說過的工具!? 至少它可能是解壓罐,反編譯類文件和掃描線解析器的方法,但我認爲這是最骯髒的方式;-)Java:簡單的方法來獲取JAR文件中類文件的方法存根?反射?
任何想法?
親切的問候
大廈在aioobe's answer,您還可以使用ASM的樹API(而不是其訪問者API)來解析包含您的JAR文件中的類文件的內容。同樣,您可以使用JarFile類讀取JAR文件中包含的文件。下面是一個如何實現的例子:
printMethodStubs
方法接受JarFile
並繼續打印出所有類文件中包含的所有方法的描述。
public void printMethodStubs(JarFile jarFile) throws Exception {
Enumeration<JarEntry> entries = jarFile.entries();
while (entries.hasMoreElements()) {
JarEntry entry = entries.nextElement();
String entryName = entry.getName();
if (entryName.endsWith(".class")) {
ClassNode classNode = new ClassNode();
InputStream classFileInputStream = jarFile.getInputStream(entry);
try {
ClassReader classReader = new ClassReader(classFileInputStream);
classReader.accept(classNode, 0);
} finally {
classFileInputStream.close();
}
System.out.println(describeClass(classNode));
}
}
}
的方法接受ClassNode
對象,並進行到描述它和它的相關聯的方法:
public String describeClass(ClassNode classNode) {
StringBuilder classDescription = new StringBuilder();
Type classType = Type.getObjectType(classNode.name);
// The class signature (e.g. - "public class Foo")
if ((classNode.access & Opcodes.ACC_PUBLIC) != 0) {
classDescription.append("public ");
}
if ((classNode.access & Opcodes.ACC_PRIVATE) != 0) {
classDescription.append("private ");
}
if ((classNode.access & Opcodes.ACC_PROTECTED) != 0) {
classDescription.append("protected ");
}
if ((classNode.access & Opcodes.ACC_ABSTRACT) != 0) {
classDescription.append("abstract ");
}
if ((classNode.access & Opcodes.ACC_INTERFACE) != 0) {
classDescription.append("interface ");
} else {
classDescription.append("class ");
}
classDescription.append(classType.getClassName()).append("\n");
classDescription.append("{\n");
// The method signatures (e.g. - "public static void main(String[]) throws Exception")
@SuppressWarnings("unchecked")
List<MethodNode> methodNodes = classNode.methods;
for (MethodNode methodNode : methodNodes) {
String methodDescription = describeMethod(methodNode);
classDescription.append("\t").append(methodDescription).append("\n");
}
classDescription.append("}\n");
return classDescription.toString();
}
的describeMethod
方法接受MethodNode
和返回描述方法的簽名的String:
public String describeMethod(MethodNode methodNode) {
StringBuilder methodDescription = new StringBuilder();
Type returnType = Type.getReturnType(methodNode.desc);
Type[] argumentTypes = Type.getArgumentTypes(methodNode.desc);
@SuppressWarnings("unchecked")
List<String> thrownInternalClassNames = methodNode.exceptions;
if ((methodNode.access & Opcodes.ACC_PUBLIC) != 0) {
methodDescription.append("public ");
}
if ((methodNode.access & Opcodes.ACC_PRIVATE) != 0) {
methodDescription.append("private ");
}
if ((methodNode.access & Opcodes.ACC_PROTECTED) != 0) {
methodDescription.append("protected ");
}
if ((methodNode.access & Opcodes.ACC_STATIC) != 0) {
methodDescription.append("static ");
}
if ((methodNode.access & Opcodes.ACC_ABSTRACT) != 0) {
methodDescription.append("abstract ");
}
if ((methodNode.access & Opcodes.ACC_SYNCHRONIZED) != 0) {
methodDescription.append("synchronized ");
}
methodDescription.append(returnType.getClassName());
methodDescription.append(" ");
methodDescription.append(methodNode.name);
methodDescription.append("(");
for (int i = 0; i < argumentTypes.length; i++) {
Type argumentType = argumentTypes[i];
if (i > 0) {
methodDescription.append(", ");
}
methodDescription.append(argumentType.getClassName());
}
methodDescription.append(")");
if (!thrownInternalClassNames.isEmpty()) {
methodDescription.append(" throws ");
int i = 0;
for (String thrownInternalClassName : thrownInternalClassNames) {
if (i > 0) {
methodDescription.append(", ");
}
methodDescription.append(Type.getObjectType(thrownInternalClassName).getClassName());
i++;
}
}
return methodDescription.toString();
}
我能想到的是使用ASM字節碼框架的最好方法。那麼至少你不必通過一個行解析器來進行反編譯輸出。事實上,獲取方法存根應該像是他們的一個Visitor接口的20行實現。
我已經使用它自己進行字節碼重寫,它非常簡單和直接(特別是如果你只是閱讀類文件)。
這是偉大的,而且確實是我搜索的。 謝謝你們! – djatomic 2010-04-22 13:40:46
這裏是所有導入,使用此代碼:'import java.io.InputStream; import java.util.Enumeration; import java.util.List; import java.util.jar.JarEntry; import java.util.jar.JarFile; import org.objectweb.asm.ClassReader; import org.objectweb.asm.Opcodes; import org.objectweb.asm.Type; import org.objectweb.asm.tree.ClassNode; import org.objectweb.asm.tree.MethodNode; import xbn.lang.SimpleXbnObject; ' – aliteralmind 2014-01-01 22:14:53
我沒有找到在網站上導入的好罐子。你能幫忙嗎?謝謝。是的,我知道舊帖子,但問題很有趣。 – MychaL 2014-04-14 18:38:37