Java Agent

Java Agent

agent是Java提供的代理插件技术,可以动态加载进目标JVM内部,收集对应应用的信息,进行字节码修改增强技术等。

Agent实现技术JVMTI

JVM提供了一套Native接口Java Virtual Machine Tool Interface(JVMTI),可以让外部程序访问JVM内部,完成虚拟机交互相关功能。通过当前接口编写agent有两种方式。

  1. 原生JVMTI的Native直接访问,编写agent需要编译打包成动态链接库.dll/.so文件。
  2. Instumentation API是Java提供的JVM相关操作的API,也是通过JVMTI实现和虚拟机交互的,编写的agent需要打包成jar加载。

Agent注入目标JVM的方式

  1. 目标应用启动时通过java启动参数附加。
#java -javaagent:[agent.jar/agent.so][=param] -jar [目标jar]
java -javaagent:./attachAgent.jar -jar Hello.jar

  1. 目标应用正在运行,通过JVM Tool提供的attach机制动态附加。
//attach pid
VirtualMachine vm = VirtualMachine.attach(pid);
try {
    //load agent
    vm.loadAgent("./agent.jar");
}finally {
    //detach 解除attach
    vm.detach();
}

JavaAgent编写

  1. 编写agent入口类,根据使用附加方式不同,实现方法不同
//启动附加实现,main方法之前执行
premain(String agentArgs, Instrumentation inst);
premain(String agentArgs);

//attach动态附加实现,附加完成直接执行
gentmain(String agentArgs, Instrumentation inst);
agentmain(String agentArgs);

  1. 编写打包指定程序入口配置MANIFEST.MF,也可以通过pom文件进行配置打包
Manifest-Version: 1.0
Agent-Class: agent.AttachAgent
Premain-Class: agent.AttachAgent
//允许重新定义已加载的类
Can-Redine-Classes: true
//允许修改已加载未初始化的类
Can-Retransform-Classes: true
  1. 内部字节码操作,通过Instrumentation.addTransformer()方法注册字节码操作ClassFileTransformer 事件,实现ClassFileTransformer.transform()方法,编写操作字节码的相关逻辑,如果class已经加载进jvm,可以执行retransformClasses重新触发transform拦截事件。
//实现ClassFileTransformer接口的addTransformer方法
public static void agentmain(String agentArgs, Instrumentation inst) {
    inst.addTransformer(new ClassFileTransformer() {
        @Override
        public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
            //对jvm加载类进行重新处理,字节码操作可用javassit、ASM
            return ClassFileTransformer.super.transform(loader, className, classBeingRedefined, protectionDomain, classfileBuffer);
        }
    });
    
    //获取已加载的类
    Class[] classs = inst.getAllLoadedClasses();
    for (Class cl : classs) {
        //重新加载,并执行transform事件
        inst.retransformClasses(cl);
    }
}
  1. Instrumentation部分方法
//注册transform事件
void addTransformer(ClassFileTransformer transformer);
//重新加载尚未初始化或实例化的类,执行Transform事件
void retransformClasses(Class<?>... classes) throws UnmodifiableClassException;
//对已经加载并且初始化的类重新定义
void redefineClasses(ClassDefinition... definitions)throws  ClassNotFoundException, UnmodifiableClassException;
//获取所有已加载类
Class[] getAllLoadedClasses();

应用场景

应用诊断:Arthas
代码调试:Debug

  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值