两者区别:
redefineClasses 是自己提供字节码文件替换掉已存在的 class 文件
retransformClasses 是在已存在的字节码文件上修改后再进行替换
替换后生效的时机
如果一个被修改的方法已经在栈帧中存在 , 则栈帧中的方法会继续使用旧字节码运行 , 新字节码会在新栈帧中运行
注意点
两个方法都是只能改变类的方法体、常量池和属性值 , 但不能新增、删除、重命名属性或方法 , 也不能修改方法的签名
二、实现 Agent1、编写方法上面我们已经说到了有两处地方可以进行 Java Agent 的加载 , 分别是 目标JVM启动时加载 和 目标JVM运行时加载 , 这两种不同的加载模式使用不同的入口函数:
1、JVM 启动时加载
入口函数如下所示:
// 函数1public static void premain(String agentArgs, Instrumentation inst);// 函数2public static void premain(String agentArgs);
JVM 首先寻找函数1 , 如果没有发现函数1 , 则会寻找函数2
2、JVM 运行时加载
入口函数如下所示:
// 函数1public static void agentmain(String agentArgs, Instrumentation inst);// 函数2public static void agentmain(String agentArgs);
与上述一致 , JVM 首先寻找函数1 , 如果没有发现函数1 , 则会寻找函数2
这两组方法的第一个参数 agentArgs 是随同 “-javaagent” 一起传入的程序参数 , 如果这个字符串代表了多个参数 , 就需要自己解析这参数 , inst 是 Instrumentation 类型的对象 , 是 JVM 自己传入的 , 我们可以那这个参数进行参数的增强操作 。
![Java高级用法,写个代理侵入你 ?](http://img.jiangsulong.com/220502/0Q93A237-1.jpg)
文章插图
2、声明方法当定义完这两组方法后 , 要使之生效还需要手动声明 , 声明方式有两种:
1、使用 MANIFEST.MF 文件
我们需要创建
resources/META-INF.MANIFEST.MF 文件 , 当 jar包打包时将文件一并打包 , 文件内容如下:
Manifest-Version: 1.0Can-Redefine-Classes: true# true表示能重定义此代理所需的类 , 默认值为 false(可选)Can-Retransform-Classes: true# true 表示能重转换此代理所需的类 , 默认值为 false (可选)Premain-Class: cbuc.life.agent.MainAgentDemo#premain方法所在类的位置Agentmain-Class: cbuc.life.agent.MainAgentDemo#agentmain方法所在类的位置
2、如果是maven项目 , 在pom.xml加入![Java高级用法,写个代理侵入你 ?](http://img.jiangsulong.com/220502/0Q93C220-2.jpg)
文章插图
3、指定 agent要让目标JVM认你这个 Agent , 你就要给目标JVM介绍这个 Agent
1、JVM 启动时加载
我们直接在 JVM 启动参数中加入 -javaagent 参数并指定 jar 文件的位置
# 将该类编译成 class 文件javac TargetJvm.java# 指定agent程序并运行该类java -javaagent:./java-agent.jar TargetJvm
2、JVM 运行时加载要实现动态调试 , 我们就不能将目标JVM停机后再重新启动 , 这不符合我们的初衷 , 因此我们可以使用 JDK 的 Attach Api 来实现运行时挂载 Agent 。
Attach Api 是 SUN 公司提供的一套扩展 API , 用来向目标 JVM 附着(attach)在目标程序上 , 有了它我们可以很方便地监控一个 JVM 。Attach Api 对应的代码位于 com.sun.tools.attach包下 , 提供的功能也非常简单:
- 列出当前所有的 JVM 实例描述
- Attach 到其中一个 JVM 上 , 建立通信管道
- 让目标JVM加载Agent
- VirtualMachine attach(String var0)
- void loadAgent(String var1)
有了 Attach Api , 我们就可以创建一个java进程 , 用它attach到对应的jvm , 并加载agent 。
以下是简单的 Attach 代码实现:
![Java高级用法,写个代理侵入你 ?](http://img.jiangsulong.com/220502/0Q93623b-3.jpg)
文章插图
推荐阅读
- 阿里架构师整理的 Netty 学习笔记之:Java NIO 网络编程
- Javascript的New、Apply、Bind、Call知多少
- 莳萝子在香肠中的用量,莳萝在烹调中的作用及用法
- 什么是Java中的反应性流?
- 莳萝对皮肤的作用,莳萝在烹调中的作用及用法
- 快速了解JavaScript的DOM模型
- Java 文件操作必知概念
- java开发框架之SSM整合框架
- 明日草的功效与作用和用法,明日叶的功效
- 普洱茶花式饮用法,水煎普洱茶的功效