gpt4 book ai didi

java - 如何查找方法中调用的所有方法(包括 Lamda)?

转载 作者:行者123 更新时间:2023-12-01 20:08:19 24 4
gpt4 key购买 nike

我想列出一个方法调用的所有方法。

void create() throws MyException {
System.out.println("TEST");
of("String").map(String::valueOf).get();
}

在这个方法中我想列出

  • System.out.println
  • map
  • 字符串::valueOf
  • 获取();

我已经习惯了以下代码,来自 how to find all methods called in a method?

public class MethodFinder {

public static void main(String[] args) throws Throwable {
ClassPool cp = ClassPool.getDefault();
CtClass ctClass = cp.get("MyClass");
CtMethod method = ctClass.getDeclaredMethod("getItem1");
method.instrument(
new ExprEditor() {
public void edit(MethodCall m)
throws CannotCompileException
{
System.out.println(m.getClassName() + "." + m.getMethodName() + " " + m.getSignature());
}
});
}
}

并获取除 String::valueOf 之外的所有方法

是否可以通过任何其他框架解决这个问题并不重要。

最佳答案

由于 String.valueOf 实际上并未由该方法调用,因此我会使用更广泛的术语,例如谈论引用方法,其中包括调用的方法。使用ASM收集所有这些的一种方法( ) 是:

import java.io.IOException;
import java.util.Optional;
import org.objectweb.asm.*;

public class FindAllReferencedMethods {
class Example {
void create() {
System.out.println("TEST");
Optional.of("String").map(String::valueOf).get();
}
}
public static void main(String[] args) throws IOException {
ClassReader r = new ClassReader(Example.class.getName());
r.accept(new ClassVisitor(Opcodes.ASM5) {
@Override
public MethodVisitor visitMethod(
int access, String name, String desc, String sig, String[] ex) {
return name.equals("create")? new MethodRefCollector(): null;
}

}, ClassReader.SKIP_DEBUG|ClassReader.SKIP_FRAMES);
}

static void referencedMethod(String owner, String name, String desc) {
System.out.println(
Type.getObjectType(owner).getClassName() + "." + name + " " + desc);
}

static class MethodRefCollector extends MethodVisitor {
public MethodRefCollector() {
super(Opcodes.ASM5);
}

@Override
public void visitMethodInsn(
int opcode, String owner, String name, String desc, boolean itf) {
referencedMethod(owner, name, desc);
}

@Override
public void visitInvokeDynamicInsn(
String name, String desc, Handle bsm, Object... bsmArgs) {
if(bsm.getOwner().equals("java/lang/invoke/LambdaMetafactory")
&& bsm.getDesc().equals(bsm.getName().equals("altMetafactory")?
ALT_SIG: MF_SIG)) {
Handle target = (Handle)bsmArgs[1];
referencedMethod(target.getOwner(), target.getName(), target.getDesc());
}
}
}
static String MF_SIG = "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;"
+"Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/"
+"MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;";
static String ALT_SIG = "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;"
+"Ljava/lang/invoke/MethodType;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;";
}

关于java - 如何查找方法中调用的所有方法(包括 Lamda)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47075009/

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