gpt4 book ai didi

java - 如何在 Java 中找到调用给定方法的所有方法?

转载 作者:太空宇宙 更新时间:2023-11-04 11:08:40 24 4
gpt4 key购买 nike

我需要获取我感兴趣的 Java 方法的所有调用者方法的列表。有没有一个工具可以帮助我解决这个问题?

编辑:我忘了提及我需要通过程序来执行此操作。我正在使用 Java Pathfinder,并且我想运行它以及调用我感兴趣的方法的所有方法。

最佳答案

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

请注意,ASM 使用 internalNames用“/”代替“.”作为分隔符。将目标方法指定为 standard declaration没有修饰符。

例如,列出可以在 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<Callee> callees = new ArrayList<Callee>();

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<JarEntry> 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();
}
}

}

关于java - 如何在 Java 中找到调用给定方法的所有方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46218583/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com