gpt4 book ai didi

使用 Byte-Buddy 的 Java 代理不起作用

转载 作者:太空宇宙 更新时间:2023-11-04 12:23:25 48 4
gpt4 key购买 nike

我需要您的帮助来找出我的实现中的问题...

我正在尝试使用 byte-buddy 实现一个简单的 JVM 运行时分析器。一般来说,我需要的是每个方法调用都将记录在我在单独对象中管理的堆栈中。

阅读了几篇文章后,我了解到最好使用“Advise”方法而不是“MethodDelegation”,这就是我的结论:

代理.java:

package com.panaya.java.agent;

import net.bytebuddy.agent.builder.AgentBuilder;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatchers;
import net.bytebuddy.utility.JavaModule;

import java.lang.instrument.Instrumentation;
import java.security.ProtectionDomain;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;

public class Agent {
private static List<Pattern> pkgIncl = new ArrayList<Pattern>();
private static List<Pattern> pkgExcl = new ArrayList<Pattern>();

private static void initMatcherPatterns(String argument) {
if (argument == null) {
System.out.println("Missing configuration argument");
return;
}

System.out.println("Argument is: " + argument);

String[] tokens = argument.split(";");

if (tokens.length < 1) {
System.out.println("Missing delimeter ;");
return;
}

for (String token : tokens) {
String[] args = token.split("=");
if (args.length < 2) {
System.out.println("Missing argument delimeter =:" + token);
return;
}

String argtype = args[0];

if (!argtype.equals("incl") && !argtype.equals("excl")) {
System.out.println("Wrong argument: " + argtype);
return;
}

String[] patterns = args[1].split(",");

for (String pattern : patterns) {
Pattern p = null;
System.out.println("Compiling " + argtype + " pattern:" + pattern + "$");
try {
p = Pattern.compile(pattern + "$");
} catch (PatternSyntaxException pse) {
System.out.println("pattern: " + pattern + " not valid, ignoring");
}
if (argtype.equals("incl"))
pkgIncl.add(p);
else
pkgExcl.add(p);
}
}

}

private static boolean isShouldInstrumentClass(String className) {
System.out.println("Testing " + className + " for match.");
boolean match = false;
String name = className.replace("/", ".");

for (Pattern p : pkgIncl) {
Matcher m = p.matcher(name);
if (m.matches()) {

match = true;
break;
}
}

for (Pattern p : pkgExcl) {
Matcher m = p.matcher(name);
if (m.matches()) {

match = false;
break;
}
}

if (match) {
System.out.println("Class " + name + "should be instrumented.");
} else {
System.out.println("Skipping class: " + name);
}
return match;
}

public static void premain(String agentArgument, Instrumentation instrumentation) {
System.out.println("Premain started");
try {
initMatcherPatterns(agentArgument);

new AgentBuilder.Default()
.with(AgentBuilder.TypeStrategy.Default.REBASE)
.type(new AgentBuilder.RawMatcher() {
public boolean matches(TypeDescription typeDescription, ClassLoader classLoader, JavaModule javaModule, Class<?> aClass, ProtectionDomain protectionDomain) {
return isShouldInstrumentClass(typeDescription.getActualName());
}
})
.transform((builder, typeDescription, classLoader) -> builder
.visit(Advice.to(ProfilingAdvice.class)
.on(ElementMatchers.any()))).installOn(instrumentation);

} catch (RuntimeException e) {
System.out.println("Exception instrumenting code : " + e);
e.printStackTrace();
}

}
}

和 ProfilingAdvice.java:

package com.panaya.java.agent;

import com.panaya.java.profiler.MethodStackCollector;
import net.bytebuddy.asm.Advice;

public class ProfilingAdvice {
@Advice.OnMethodEnter
public static void enter(@Advice.Origin("#t.#m") String signature) {
System.out.println("OnEnter :" + signature);
try {
MethodStackCollector.getInstance().push(signature);
} catch (Exception e) {
e.printStackTrace();
}
}

@Advice.OnMethodExit
public static void exit(@Advice.Return long value) {
System.out.println("OnExit - value = " + value);
try {
MethodStackCollector.getInstance().pop();
} catch (Exception e) {
e.printStackTrace();
}

}
}

由于某种原因,根本不会调用 ProfilingAdvice 类中的“enter”和“exit”方法。

我做错了什么?

谢谢,埃拉德。

最佳答案

我尝试了您的示例,并在减少打印命令的退出建议和匹配器以仅匹配某些类foo.Bar之后:

package foo;
public class Bar {
public long qux() { return 0L; }
}

仪器工作没有问题。我发现您的 Advice 匹配器指定 any() 而您的 ProfilingAdvice 需要 long 返回类型有点可疑。您是否尝试仅打印到控制台,而不在建议中添加任何注释?

您可以通过设置来调试此类问题:

new AgentBuilder.Default()
.with(AgentBuilder.Listener.StreamWriting.toSystemOut());

检测期间的潜在错误将打印到控制台。

关于使用 Byte-Buddy 的 Java 代理不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38608048/

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