Java:从JAR文件中的类文件中获取方法存根的简单方法?反射
我正在寻找一种方法来获取jar文件中所有类的方法存根列表。 我不知道从哪里开始。。。我可以使用反射、Javassist或其他一些我还没有听说过的工具吗!? 至少可以解包jar、反编译类文件并用行解析器扫描方法,但我认为这是最肮脏的方式;-) 有什么想法吗Java:从JAR文件中的类文件中获取方法存根的简单方法?反射,java,reflection,class,jar,methods,Java,Reflection,Class,Jar,Methods,我正在寻找一种方法来获取jar文件中所有类的方法存根列表。 我不知道从哪里开始。。。我可以使用反射、Javassist或其他一些我还没有听说过的工具吗!? 至少可以解包jar、反编译类文件并用行解析器扫描方法,但我认为这是最肮脏的方式;-) 有什么想法吗 我能想到的最好的方法是使用ASM字节码框架。这样,至少您不必使用行解析器进行一些反编译输出。事实上,获取方法存根应该类似于一个访问者接口的20行实现 我自己也用过它来重写字节码,它非常简单和直接(特别是如果你只是在读类文件的话) 在此基础上,您
我能想到的最好的方法是使用ASM字节码框架。这样,至少您不必使用行解析器进行一些反编译输出。事实上,获取方法存根应该类似于一个访问者接口的20行实现 我自己也用过它来重写字节码,它非常简单和直接(特别是如果你只是在读类文件的话) 在此基础上,您还可以使用ASM的树API(与其访问者API相反)来解析JAR文件中包含的类文件的内容。此外,还可以使用类读取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));
}
}
}
describeMethod
方法接受并返回描述方法签名的字符串:
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();
}
公共字符串描述方法(MethodNode MethodNode){
StringBuilder methodDescription=新建StringBuilder();
类型returnType=Type.getReturnType(methodNode.desc);
Type[]argumentTypes=Type.getArgumentTypes(methodNode.desc);
@抑制警告(“未选中”)
List thrownInternalClassNames=methodNode.exceptions;
if((methodNode.access&opcode.ACC_PUBLIC)!=0){
方法说明。附加(“公共”);
}
if((methodNode.access&opcode.ACC_PRIVATE)!=0){
方法描述。附加(“私有”);
}
if((methodNode.access&opcode.ACC_PROTECTED)!=0){
方法说明。附加(“受保护”);
}
if((methodNode.access&opcode.ACC_STATIC)!=0){
methodDescription.append(“静态”);
}
if((methodNode.access&opcode.ACC_ABSTRACT)!=0){
方法描述。追加(“摘要”);
}
if((methodNode.access&opcode.ACC_SYNCHRONIZED)!=0){
方法描述。追加(“同步”);
}
append(returnType.getClassName());
方法说明。追加(“”);
methodDescription.append(methodNode.name);
方法说明。追加(“”);
for(int i=0;i0){
方法说明。追加(“,”);
}
append(argumentType.getClassName());
}
方法说明。追加(“)”;
如果(!thrownInternalClassNames.isEmpty()){
方法描述。追加(“抛出”);
int i=0;
for(字符串thrownInternalClassName:thrownInternalClassName){
如果(i>0){
方法说明。追加(“,”);
}
append(Type.getObjectType(thrownInternalClassName.getClassName());
i++;
}
}
return methodDescription.toString();
}
这很好,完全符合我搜索的内容。谢谢你们!以下是使用此代码的所有导入:import java.io.InputStream;导入java.util.Enumeration;导入java.util.List;导入java.util.jar.JarEntry;导入java.util.jar.jar文件;导入org.objectweb.asm.ClassReader;导入org.objectweb.asm.opcode;导入org.objectweb.asm.Type;导入org.objectweb.asm.tree.ClassNode;导入org.objectweb.asm.tree.MethodNode;导入xbn.lang.SimpleXbnObject代码>我在网站上找不到好的jar导入。你能帮忙吗?非常感谢。是的,我知道以前的帖子,但问题很有趣。
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();
}