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

如何用Byte Buddy拦截指定类/包中初始化的ExecutorService方法?

用Byte Buddy拦截特定类/包初始化的ExecutorService实例方法

要实现仅拦截特定类(比如TestClient)或包内初始化的ExecutorService实例方法,核心思路是标记目标来源的实例,再在拦截时只处理带标记的实例。以下是两种可行方案:

方案1:标记工厂方法返回的目标实例

如果你的ExecutorService是通过Executors这类工厂类创建的,可通过拦截工厂方法的调用上下文,给目标类发起的创建请求返回带标记的实例,后续仅拦截带标记的实例方法。

步骤1:定义标记接口

用一个空接口标记目标实例,无需实现逻辑:

public interface TargetExecutorMarker {}

步骤2:拦截工厂方法并标记实例

拦截Executors的静态创建方法,当调用者是目标类/包时,返回子类化并实现标记接口的实例:

public class ExecutorCreationInterceptor {
    @RuntimeType
    public static Object intercept(@SuperCall Callable<?> superCall, @CallerClass Class<?> callerClass) throws Exception {
        Object originalExecutor = superCall.call();
        
        // 仅给目标包/类发起的创建请求标记实例
        if (callerClass.getName().startsWith("com.your.target.package") || callerClass.equals(TestClient.class)) {
            // 通过Byte Buddy子类化原实例并添加标记接口
            return new ByteBuddy()
                .subclass(originalExecutor.getClass())
                .implement(TargetExecutorMarker.class)
                .method(ElementMatchers.any())
                .intercept(MethodCall.invokeSelf())
                .make()
                .load(callerClass.getClassLoader())
                .getLoaded()
                .getDeclaredConstructor()
                .newInstance();
        }
        
        return originalExecutor;
    }
}

步骤3:拦截ExecutorService方法并过滤标记实例

拦截所有ExecutorService的方法,但仅处理带TargetExecutorMarker标记的实例:

public class ExecutorMethodInterceptor {
    @RuntimeType
    public static Object intercept(@This Object instance, @Origin Method method, @AllArguments Object[] args) throws Exception {
        // 仅处理目标标记的实例
        if (instance instanceof TargetExecutorMarker) {
            // 这里添加你的拦截逻辑:日志、参数修改、耗时统计等
            System.out.printf("拦截到目标ExecutorService方法:%s%n", method.getName());
        }
        
        // 调用原方法逻辑
        return method.invoke(instance, args);
    }
}

组装Agent

将上述拦截逻辑整合到Byte Buddy Agent中:

new AgentBuilder.Default()
    // 拦截Executors的静态创建方法
    .type(ElementMatchers.named("java.util.concurrent.Executors"))
    .transform((builder, typeDesc, classLoader, module) ->
        builder.method(ElementMatchers.isStatic().and(ElementMatchers.returns(ElementMatchers.isSubTypeOf(ExecutorService.class))))
            .intercept(MethodDelegation.to(ExecutorCreationInterceptor.class))
    )
    // 拦截所有ExecutorService的方法
    .type(ElementMatchers.isSubTypeOf(ExecutorService.class))
    .transform((builder, typeDesc, classLoader, module) ->
        builder.method(ElementMatchers.any())
            .intercept(MethodDelegation.to(ExecutorMethodInterceptor.class))
    )
    .installOn(instrumentation);

方案2:追踪目标类持有的ExecutorService实例

如果TestClient直接持有ExecutorService字段,可通过拦截字段赋值来记录目标实例,后续拦截时校验实例是否在记录集合中。

步骤1:实现字段拦截器记录目标实例

public class ExecutorFieldInterceptor {
    // 线程安全集合存储目标实例
    private static final Set<Object> targetExecutors = Collections.synchronizedSet(new HashSet<>());

    @RuntimeType
    public static void setExecutor(@This TestClient client, @Argument(0) ExecutorService executor) {
        // 记录TestClient持有的ExecutorService实例
        targetExecutors.add(executor);
    }

    // 提供校验方法
    public static boolean isTargetExecutor(Object executor) {
        return targetExecutors.contains(executor);
    }
}

步骤2:修改ExecutorMethodInterceptor校验实例

public class ExecutorMethodInterceptor {
    @RuntimeType
    public static Object intercept(@This Object instance, @Origin Method method, @AllArguments Object[] args) throws Exception {
        if (ExecutorFieldInterceptor.isTargetExecutor(instance)) {
            // 执行你的拦截逻辑
            System.out.printf("拦截到TestClient持有的ExecutorService方法:%s%n", method.getName());
        }
        
        return method.invoke(instance, args);
    }
}

组装Agent

new AgentBuilder.Default()
    // 拦截TestClient的ExecutorService字段赋值
    .type(ElementMatchers.named("com.your.package.TestClient"))
    .transform((builder, typeDesc, classLoader, module) ->
        builder.field(ElementMatchers.type(ElementMatchers.isSubTypeOf(ExecutorService.class)))
            .intercept(FieldAccessor.ofField("executor").andThen(FieldDelegation.to(ExecutorFieldInterceptor.class)))
    )
    // 拦截ExecutorService方法
    .type(ElementMatchers.isSubTypeOf(ExecutorService.class))
    .transform((builder, typeDesc, classLoader, module) ->
        builder.method(ElementMatchers.any())
            .intercept(MethodDelegation.to(ExecutorMethodInterceptor.class))
    )
    .installOn(instrumentation);

注意事项

  • 若遇到不可子类化的ExecutorService实现(如ForkJoinPool),可改用添加隐藏字段的方式标记实例,避免子类化限制。
  • 标记/记录实例的操作需保证线程安全,避免并发场景下的遗漏或误判。
  • 若目标类通过多种方式创建ExecutorService,需覆盖所有创建入口的拦截逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 14:40:34