我正在评估使用 ASM 作为框架来实现一些字节码分析的可能性。到目前为止,我一直在玩一些示例,但有几件事需要整理:1)我看不到如何使用 MethodVisitor 类检测方法的完全签名(完整的参数类型名称和形式名称)。
2)如果正在分析的.class文件关联了java源,如何将字节码指令与源中的行号链接起来
3)如何区分ClassVisitor中的实例字段和静态字段
我正在评估使用 ASM 作为框架来实现一些字节码分析的可能性。到目前为止,我一直在玩一些示例,但有几件事需要整理:1)我看不到如何使用 MethodVisitor 类检测方法的完全签名(完整的参数类型名称和形式名称)。
2)如果正在分析的.class文件关联了java源,如何将字节码指令与源中的行号链接起来
3)如何区分ClassVisitor中的实例字段和静态字段
1)我看不到如何使用 MethodVisitor 类检测方法的完全签名(完整的参数类型名称和正式名称)。
你不能。ClassVisitor 收到一个电话,例如
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions)
在返回 MethodVistor 之前,您需要从您感兴趣的参数中捕获信息。
如果代码编译时带有调试信息,则可以通过以下方式获取参数和局部变量名称visitLocalVariable
2)如果正在分析的.class文件关联了java源,如何将字节码指令与源中的行号链接起来
方法中的代码会有visitLabel形式的源信息“指令”
3)如何区分ClassVisitor中的实例字段和静态字段
由access
修饰符。采用Modifier.isStatic(access)
1)实际上我设法提取详细的方法签名(参数类型和名称以及返回类型)作为 MethodVisitor 实现的一部分。备注:这仅在编译包含调试信息的类文件时才有效。
@Override
public MethodVisitor visitMethod(int access, String name,
String desc, String signature, String[] exceptions) {
try {
final LinkedList<String> parameters;
final boolean isStaticMethod;
Type[] args = Type.getArgumentTypes(desc);
Type ret = Type.getReturnType(desc);
parameters = new LinkedList<String>();
isStaticMethod = Modifier.isStatic(access);
return new MethodVisitor(Opcodes.ASM5) {
// assume static method until we get a first parameter name
public void visitLocalVariable(String name, String description, String signature, Label start, Label end, int index) {
if (isStaticMethod && parameters.size() < args.length) {
parameters.add(args[index].getClassName()+" " +name);
} else if (index > 0 && parameters.size() < args.length) {
// for non-static the 0th arg is "this" so we need to offset by -1
parameters.add(args[index-1].getClassName() +" " +name);
}
}
@Override
public void visitEnd() {
System.out.println("Method: "+ret.getClassName()+" "+name+"("+String.join(", ", parameters)+")");
super.visitEnd();
}
};
} catch (Exception e) {
throw e;
}
这将为标准 main 生成以下输出:
方法:void main(java.lang.String[] args)
2)只要编译发生时包含源,参数Label start
和包含有关相应源的信息。Label end
3)见@Peter Lawrey回复。