根据aioobe的回答,您还可以使用ASM的树API(而不是其访问者API)来解析JAR文件中包含的类文件的内容。同样,您可以使用JarFile类读取JAR文件中包含的文件。这是如何完成此操作的示例:
该
printMethodStubs方法接受a
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)); } }}该
describeClass方法接受一个
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 & Oppres.ACC_PUBLIC) != 0) { classDescription.append("public "); } if ((classNode.access & Oppres.ACC_PRIVATE) != 0) { classDescription.append("private "); } if ((classNode.access & Oppres.ACC_PROTECTED) != 0) { classDescription.append("protected "); } if ((classNode.access & Oppres.ACC_ABSTRACT) != 0) { classDescription.append("abstract "); } if ((classNode.access & Oppres.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方法接受a
MethodNode并返回一个描述方法签名的字符串:
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 & Oppres.ACC_PUBLIC) != 0) { methodDescription.append("public "); } if ((methodNode.access & Oppres.ACC_PRIVATE) != 0) { methodDescription.append("private "); } if ((methodNode.access & Oppres.ACC_PROTECTED) != 0) { methodDescription.append("protected "); } if ((methodNode.access & Oppres.ACC_STATIC) != 0) { methodDescription.append("static "); } if ((methodNode.access & Oppres.ACC_ABSTRACT) != 0) { methodDescription.append("abstract "); } if ((methodNode.access & Oppres.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();}


