苏州网站模板建站,项目计划书怎么写,丽水城乡建设局网站,泰安网站建设泽讯Java Agent是什么#xff1f; Java Agent是Java平台提供的一个强大工具#xff0c;它可以在运行时修改或增强Java应用程序的行为。是在JDK1.5以后引入的#xff0c;它能够在不影响正常编译的情况下修改字节码#xff0c;相当于是在main方法执行之前的拦截器#xff0c;也叫…Java Agent是什么 Java Agent是Java平台提供的一个强大工具它可以在运行时修改或增强Java应用程序的行为。是在JDK1.5以后引入的它能够在不影响正常编译的情况下修改字节码相当于是在main方法执行之前的拦截器也叫premain也就是会先执行premain方法然后再执行main方法。 使用javaagent可以用于执行一个jar包并且对这个java包有两个要求
jar包的MANIFEST.MF文件必须指定Premain-Class项Premain-Class指定的那个类必须实现premain()方法 当程序启动的时候JVM会首先检查-javaagent所指定的jar包内Premain-Class这个类中的premain方法。
Java Agent的使用场景
代码注入增强允许在程序运行时对字节码进行操作可以实现功能的增强。性能监控调优可以监控应用程序方法执行时间、调用次数类加载的一些信息进行性能检测以及对一些问题的定位分析比如一些性能监控和诊断工具如Pinpoint、Skywalking、Zipkin、Arthas等。日志记录审计Java Agent可以在方法执行前后记录方法的调用信息包括方法名、参数、返回值等动态记录应用程序的运行日志。
Java Agent的简单使用
1.基于 Instrumentation 接口和premain()方法实现
新建一个maven项目添加maven-jar-plugin插件依赖用于打包并生成MANIFREST.MF文件。
buildfinalNameagenttestone/finalNamepluginsplugingroupIdorg.apache.maven.plugins/groupIdartifactIdmaven-jar-plugin/artifactIdversion3.2.0/versionconfigurationarchive!--自动添加META-INF/MANIFEST.MF --manifestaddClasspathtrue/addClasspath/manifestmanifestEntries!--permain方法所在类的完全限定名--Premain-Classcom.yifanghub.agent.PremainTest/Premain-ClassAgent-Classcom.yifanghub.agent.PremainTest/Agent-ClassCan-Redefine-Classestrue/Can-Redefine-ClassesCan-Retransform-Classestrue/Can-Retransform-Classes/manifestEntries/archive/configuration/plugin/plugins/build其中manifestEntries配置了一些属性 Premain-Class包含premain方法的类类的全路径名 Agent-Class包含agentmain方法的类类的全路径名 Can-Redefine-Classes是否可以重定义此代理所需的类默认为false Can-Retransform-Classes是否可以重新转换此代理类所需的类默认为false 新建premain方法测试类其中premain方法agentArgs可以通过命令行传入
package com.yifanghub.agent;
import java.lang.instrument.Instrumentation;public class PremainTest {public static void premain(String agentArgs, Instrumentation inst) {System.out.println(premain执行----);System.out.println(Hello agent testagentArgsagentArgs);}
}新建main方法测试类新建一个项目
package com.yifanghub.agent;public class PremainAgent {public static void main(String[] args) {System.out.println(agent测试走起main方法执行);}
}执行main方法打印如下
agent测试走起main方法执行idea配置编辑启动类-Add VMOptions
-javaagent:D:\javaagent-demo\javaagent-demo-1.0-SNAPSHOT.jar123运行程序打印如下
premain执行----
Hello agent testagentArgs123
agent测试走起main方法执行注意事项 agent的方法名必须是premain否则会报错。 agent抛出异常会导致主程序的启动失败。 premain方法只允许以下两种定义方式 1public static void premain(String agentArgs, Instrumentation inst)2public static void premain(String agentArgs)JVM 会优先加载带有Instrumentation参数的方法1加载成功忽略 2如果1 没有加载 2 方法。2.基于 Attach 接口和agentmain()方法实现
JDK 1.6后引入了agentmain模式同样提供了一个agentmain方法可以在main方法执行之后运行
public static void agentmain (String agentArgs, Instrumentation inst)
public static void agentmain (String agentArgs)1创建agentmian方法类
import java.lang.instrument.Instrumentation;public class AgentmainTest {public static void agentmain(String agentArgs, Instrumentation inst) {System.out.println(agentmain执行----);System.out.println(Hello I am agentmain testagentArgsagentArgs);}
}将上面代码打包名字为javaagent-demo2-1.0-SNAPSHOT.jar
2创建被注入的main方法测试类新建一个项目这里主要使用一个for循环打印让程序处于一直运行状态
public class MainTest {public static void main(String[] args) {System.out.println(开始执行mian);for (int i 1; i 100000; i) {System.out.println(第 i 次循环);try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}}}
}3创建attach项目编写main方法 这里用到了com.sun.tools.attach 包下面的VirtualMachine工具类来实现该类表示一个Java虚拟机对象该类的一些接口如下
list()获取当前所有JVM列表 attach()根据进程id连接到jvm上detach()断开连接 loadAgent()加载agent
如果idea里面不能导入VirtualMachine类导入JDK里面lib下的tool.jar包即可 attach方法如下
import com.sun.tools.attach.*;
import java.io.IOException;
import java.util.List;public class AgentDemo4Test {public static void main(String[] args) throws IOException, AttachNotSupportedException, AgentLoadException, AgentInitializationException {System.out.println(AgentDemo4Test);ListVirtualMachineDescriptor list VirtualMachine.list();for (VirtualMachineDescriptor vmd : list) {if(vmd.displayName().equals(agent.MainTest)){System.out.println(vmd.displayName());VirtualMachine vm VirtualMachine.attach(vmd.id());vm.loadAgent(D:\\javaagent-demo2-1.0-SNAPSHOT.jar,123456);vm.detach();}}}
}4启动运行MainTest类第2步打印for循环的程序然后执行上面AgentDemo4Test类的main方法输出如下 可以看到我们的agentmain方法的代理已经生效其中attach方法可以连接到一个正在运行的Java进程当中之后便可以通过loadAgent方法将我们的jar包注入到对应的进程当中然后被注入的进程就好调用jar包里的agentmain方法。
注意事项
agentmain()方法会在加载之时立即执行如果agentmain执行失败或抛出异常JVM 会忽略掉错误不会影响到正在运行的程序。
参考https://www.cnblogs.com/LittleHann/p/17462796.html