javaagent + javassist实战

Javaagent提供的能力可以让我们在main之前(premain)、之后(agentmain)做一些事情,向Skywalking这类监控就是基于javaagent实现的。
Javassist提供的能力可以动态修改字节码,可以在不修改源码的基础上动态编译class文件 参考2 参考3
我们尝试基于现有服务通过javaagent+javassist的方式对原类做功能增强,开始!

源码地址参考

原服务:wsth
增强代理工程:javagent

javaagent工程

  • 类图
    在这里插入图片描述

  • MANIFEST.MF配置Premain-Class
    为防止package后被覆盖,pom增加插件

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    <version>3.1.0</version>
    <configuration>
        <archive>
            <!--自动添加META-INF/MANIFEST.MF -->
            <manifest>
                <addClasspath>true</addClasspath>
            </manifest>
            <manifestEntries>
                <Premain-Class>com.dragon.hei.javaagent.premain.MethodTimePreMain</Premain-Class>
                <!--<Agent-Class>com.dragon.hei.javaagent.premain.MethodTimePreMain</Agent-Class>-->
                <Can-Redefine-Classes>true</Can-Redefine-Classes>
                <Can-Retransform-Classes>true</Can-Retransform-Classes>
            </manifestEntries>
        </archive>
    </configuration>
</plugin>
  • 增加premain函数
import com.dragon.hei.javaagent.enhancer.ClassEnhancer;
import com.dragon.hei.javaagent.enhancer.javassist.LogEnhancer;
import com.dragon.hei.javaagent.enhancer.javassist.TimeCostEnhancer;
import com.dragon.hei.javaagent.transformer.MyClassTransformer;

import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.Instrumentation;

public class MethodTimePreMain {

    public static void premain(String agentArgs, Instrumentation inst) {

        //System.out.println("自定义premain:" + agentArgs);

        inst.addTransformer(myTransformer(), true);
    }

    private static ClassFileTransformer myTransformer(){

        ClassEnhancer timeCostEnhancer = new TimeCostEnhancer();
        ClassEnhancer logEnhancer = new LogEnhancer();
        return new MyClassTransformer(logEnhancer, timeCostEnhancer);
    }
}
  • 增强器链
    详见 javagent
    LogEnhancer:针对被代理类的方法入口出口打印参数
    TimeCostEnhancer:针对被代理类的方法结束时打印接口耗时

wsth工程

  • wsth启动类或main函数配置jvm启动参数:-javaagent:/xxx/javagent/target/javagent-1.0-SNAPSHOT.jar
  • main函数,本次仅针对DefaultRuleChain做增强
public static void main(String[] args) {
        // aviator上下文
        AviatorContext context = buildContext();

        // 存储表达式执行结果
        List<AbstractAviatorRule> response = new ArrayList<>();

        // 规则chain
        RuleChain ruleChain = new DefaultRuleChain(rules());
        ruleChain.matchRule(context, response);

        System.out.println("规则链执行结果:"+JSON.toJSONString(response));
    }
  • 执行结果
    在这里插入图片描述

遇到的问题

  • 如果main函数或应用启动或执行失败,可能是agent的依赖在应用中不存在,可以在应用war包中增加对应的jar或修改pom
  • javassist类获取不到,可能是className格式问题,"/“替换成”."
  • LogEnhancer打印参数无法识别"$$",暂时写死"$1","$2"

小结

本篇仅在不修改源码情况下增强字节码功能的一次尝试,增强器代码结构性、完整性、可通用性比较差,慢慢完善增加一些实用、可复用的功能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值