You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ByteBuddy Agent问题:HttpClient.send的Advice未调用Transport.send

问题:ByteBuddy开发Java Agent时调用外部静态方法无输出,内联日志正常

我用ByteBuddy开发Java Agent,目标是统计java.net.http.HttpClient类send方法的执行耗时,但遇到异常:Advice类的exit方法中调用Transport.send()时没有任何输出,若将日志语句直接内联到exit方法则可正常执行。

相关代码

premain方法

public static void premain(String arguments, Instrumentation instrumentation) {
    new AgentBuilder.Default()
        .ignore(ElementMatchers.none())
        .with(Listener.StreamWriting.toSystemOut().withErrorsOnly())
        .type(hasSuperType(named("java.net.http.HttpClient")))
        .transform((builder, typeDescription, classLoader,
            module, protectionDomain) -> {
          return builder
              .visit(Advice.to(SendAdvice.class)
                  .on(hasMethodName("send")
                      .and(returns(named("java.net.http.HttpResponse")))));
        })
        .asTerminalTransformation()
        .installOn(instrumentation);
  }

Transport类

public class Transport {
    public static void send() {
        System.out.println("hello static");
  }
}

SendAdvice类

class SendAdvice {
  @Advice.OnMethodEnter()
  public static long start() {
    return System.nanoTime();
  }

  @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
  public static void exit(
      @Advice.Enter long startTime) throws MalformedURLException {
    Transport.send(System.nanoTime() - startTime);
  }
}

问题分析

  1. 方法签名不匹配:Advice的exit方法中调用Transport.send(long),但Transport类中定义的是无参的send(),参数不匹配导致调用失败。加上suppress = Throwable.class后,异常被静默吞掉,无法看到报错信息。
  2. 类加载器隔离:Java Agent的类加载器与HttpClient所属的Bootstrap类加载器可能存在隔离,导致Transport类无法被正确加载或访问,同样因为异常被抑制而无法察觉。
  3. 类型匹配不准确:hasSuperType(named("java.net.http.HttpClient"))可能匹配到非目标子类,导致Advice没有正确织入到HttpClient的send方法上。

解决方案

  1. 修复方法签名:调整Transport类的send方法,使其接收long类型参数,匹配调用逻辑:
public class Transport {
    public static void send(long cost) {
        System.out.println("send方法执行耗时:" + cost + "纳秒");
    }
}
  1. 移除异常抑制,排查真实错误:暂时去掉suppress = Throwable.class,或添加异常捕获日志,明确问题根源:
@Advice.OnMethodExit(onThrowable = Throwable.class)
public static void exit(@Advice.Enter long startTime) throws MalformedURLException {
    try {
        Transport.send(System.nanoTime() - startTime);
    } catch (Throwable t) {
        t.printStackTrace();
    }
}
  1. 调整类型匹配规则:直接匹配HttpClient类而非父类,确保Advice织入目标方法:
.type(named("java.net.http.HttpClient"))
  1. 确保类加载可见性:如果Transport类无法被Bootstrap类加载器访问,可通过AgentBuilder配置将其加入Bootstrap类路径,或使用AgentBuilder.Default().with(AgentBuilder.TypeStrategy.Default.REDEFINE)确保类加载策略正确。

内容的提问来源于stack exchange,提问作者Daven

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 04:02:20