TransmittableThreadLocal使用JavaAgent动态代理机制分析

本文详细解析了如何通过JavaAgent和TTL (Transmittable Thread Local) 实现对ThreadPoolExecutor等类的动态代理,包括参数解析、日志设置和不同Transformlet的使用过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文不提及TTL的作用,仅从源码层面分析TTL是怎么使用JavaAgent来动态代理的
依赖如下:

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>transmittable-thread-local</artifactId>
    <version>2.11.4</version>
</dependency>

JavaAgent字节码方式增强

代码入口

com.alibaba.ttl.threadpool.agent.TtlAgent

使用方式

启动jar的时候,附加上参数-javaagent:/xx/transmittable-thread-local.jar(目录自己放好)

/opt/soft/jdk/jdk1.8.0_191/bin/java
    -javaagent:/xx/transmittable-thread-local.jar 
    -jar /opt/xxx.jar

源码分析

执行步骤

第一步:解析参数(可不传),将“xx:xx”解析为Map<String, String>

常用参数:
ttl.agent.disable.inheritable.for.thread.pool:true
ttl.agent.logger:STDOUT
ttl.agent.enable.timer.task:false

第二步:设置日志输出参数类型,比如STDOUT(不设置默认就是STDOUT, loggerImplType = 0)

STDOUT: 标准输出
STDERR: 标准错误输出

第三步:组装JavassistTransformlet,分为三种类型如下

TtlExecutorTransformlet处理的类:ThreadPoolExecutor及其子类、ScheduledThreadPoolExecutor
TtlForkJoinTransformlet处理的类:ForkJoinTask、ForkJoinPool
默认开启。TtlTimerTaskTransformlet处理的类:仅处理TimeTask子类

第四步:调用生效的时机到了

执行生效方法:inst.addTransformer(transformer, true);

TtlAgent入口premain()方法

Java中的javaAgent一般会涉及到 MANIFEST.MF配置类、premain()方法入口,下面来解析

  • MANIFEST.MF配置如下:

可见Premain-Class指向了com.alibaba.ttl.threadpool.agent.TtlAgent类

Manifest-Version: 1.0
Created-By: Apache Maven 3.5.4
Built-By: jerry
Build-Jdk: 11.0.1
Boot-Class-Path: transmittable-thread-local-2.10.2.jar
Can-Redefine-Classes: false
Can-Retransform-Classes: true
Can-Set-Native-Method-Prefix: false
Premain-Class: com.alibaba.ttl.threadpool.agent.TtlAgent

接来下解析TllAgent.java入口类,其premain()方法如下

/** TTL javaAgent字节码增强premain入口类 **/
public static void premain(String agentArgs, @NonNull Instrumentation inst) {
   
    // 第一步:解析参数(可不传),将“xx:xx”解析为Map<String, String>
    // 常用参数:ttl.agent.disable.inheritable.for.thread.pool:true
    //         ttl.agent.logger:STDOUT
    //         ttl.agent.enable.timer.task:false
    kvs = splitCommaColonStringToKV(agentArgs);

    // 第二步:设置日志输出参数类型,比如STDOUT(不设置默认就是STDOUT, loggerImplType = 0)
    // - STDOUT: 标准输出
    // - STDERR: 标准错误输出
    Logger.setLoggerImplType(getLogImplTypeFromAgentArgs(kvs));
    final Logger logger = Logger.getLogger(TtlAgent.class);

    try {
   
        logger.info("[TtlAgent.premain] begin, agentArgs: " + agentArgs + ", Instrumentation: " + inst);
        // 获取是否开启 "关闭继承" 的能力,不传默认返回false
        final boolean disableInheritableForThreadPool = isDisableInheritableForThreadPool();

        // 第三步:组装JavassistTransformlet
        final List<JavassistTransformlet> transformletList = new ArrayList<JavassistTransformlet>();
        // TtlExecutorTransformlet处理的类:ThreadPoolExecutor及其子类、ScheduledThreadPoolExecutor
        transformletList.add(new TtlExecutorTransformlet(disableInheritableForThreadPool));
        // TtlForkJoinTransformlet处理的类:ForkJoinTask、ForkJoinPool
        transformletList.add(new TtlForkJoinTransformlet(disableInheritableForThreadPool));
        // 默认开启。TtlTimerTaskTransformlet处理的类:仅处理TimeTask子类
        if (isEnableTimerTask()) transformletList.add(new TtlTimerTaskTransformlet());

        
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值