java 找出调用的方法_如何找到用Java调用给定方法的所有方法?

小编典典

为了分析字节码,我建议使用ASM。给定要分析的类列表,可以使访问者找到您感兴趣的方法调用。下面是一个分析jar文件中类的实现。

请注意,ASM使用带有’/’而不是’。的internalNames。作为分隔符。将目标方法指定为不带修饰符的标准声明。

例如,列出在Java运行时jar中可能正在调用System.out.println(“ foo”)的方法:

java -cp "classes;asm-3.1.jar;asm-commons-3.1.jar" App \

c:/java/jdk/jre/lib/rt.jar \

java/io/PrintStream "void println(String)"

编辑:添加了源代码和行号:请注意,这仅指示每个调用方法的最后一个目标方法调用-原始q只想知道哪些方法。我将其作为练习供读者显示调用方法声明的行号或每个目标调用的行号,具体取决于您实际要执行的操作。:)

结果是:

LogSupport.java:44 com/sun/activation/registries/LogSupport log (Ljava/lang/String;)V

LogSupport.java:50 com/sun/activation/registries/LogSupport log (Ljava/lang/String;Ljava/lang/Throwable;)V

Throwable.java:498 java/lang/Throwable printStackTraceAsCause (Ljava/io/PrintStream;[Ljava/lang/StackTraceElement;)V

885 methods invoke java/io/PrintStream println (Ljava/lang/String;)V

资源:

public class App {

private String targetClass;

private Method targetMethod;

private AppClassVisitor cv;

private ArrayList callees = new ArrayList();

private static class Callee {

String className;

String methodName;

String methodDesc;

String source;

int line;

public Callee(String cName, String mName, String mDesc, String src, int ln) {

className = cName; methodName = mName; methodDesc = mDesc; source = src; line = ln;

}

}

private class AppMethodVisitor extends MethodAdapter {

boolean callsTarget;

int line;

public AppMethodVisitor() { super(new EmptyVisitor()); }

public void visitMethodInsn(int opcode, String owner, String name, String desc) {

if (owner.equals(targetClass)

&& name.equals(targetMethod.getName())

&& desc.equals(targetMethod.getDescriptor())) {

callsTarget = true;

}

}

public void visitCode() {

callsTarget = false;

}

public void visitLineNumber(int line, Label start) {

this.line = line;

}

public void visitEnd() {

if (callsTarget)

callees.add(new Callee(cv.className, cv.methodName, cv.methodDesc,

cv.source, line));

}

}

private class AppClassVisitor extends ClassAdapter {

private AppMethodVisitor mv = new AppMethodVisitor();

public String source;

public String className;

public String methodName;

public String methodDesc;

public AppClassVisitor() { super(new EmptyVisitor()); }

public void visit(int version, int access, String name,

String signature, String superName, String[] interfaces) {

className = name;

}

public void visitSource(String source, String debug) {

this.source = source;

}

public MethodVisitor visitMethod(int access, String name,

String desc, String signature,

String[] exceptions) {

methodName = name;

methodDesc = desc;

return mv;

}

}

public void findCallingMethodsInJar(String jarPath, String targetClass,

String targetMethodDeclaration) throws Exception {

this.targetClass = targetClass;

this.targetMethod = Method.getMethod(targetMethodDeclaration);

this.cv = new AppClassVisitor();

JarFile jarFile = new JarFile(jarPath);

Enumeration entries = jarFile.entries();

while (entries.hasMoreElements()) {

JarEntry entry = entries.nextElement();

if (entry.getName().endsWith(".class")) {

InputStream stream = new BufferedInputStream(jarFile.getInputStream(entry), 1024);

ClassReader reader = new ClassReader(stream);

reader.accept(cv, 0);

stream.close();

}

}

}

public static void main( String[] args ) {

try {

App app = new App();

app.findCallingMethodsInJar(args[0], args[1], args[2]);

for (Callee c : app.callees) {

System.out.println(c.source+":"+c.line+" "+c.className+" "+c.methodName+" "+c.methodDesc);

}

System.out.println("--\n"+app.callees.size()+" methods invoke "+

app.targetClass+" "+

app.targetMethod.getName()+" "+app.targetMethod.getDescriptor());

} catch(Exception x) {

x.printStackTrace();

}

}

}

```

2020-09-27

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值