佛山用户网站建设,设计类的网站和简介,自己可以做网站推广吗,中企动力电话分为两种 程序运行前的agent#xff1a;premain 程序运行中的agent#xff1a;agentmain 在程序运行前的agent
javaagent是java命令的一个参数#xff0c;所以需要通过-javaagent 来指定一个jar包#xff08;就是我们要做的代理包#xff09;能够实现在主程序运行前来执行…分为两种 程序运行前的agentpremain 程序运行中的agentagentmain 在程序运行前的agent
javaagent是java命令的一个参数所以需要通过-javaagent 来指定一个jar包就是我们要做的代理包能够实现在主程序运行前来执行我们jar中的方法 1.pom文件中
pluginsplugingroupIdorg.apache.maven.plugins/groupIdartifactIdmaven-compiler-plugin/artifactIdversion3.5.1/version!-- 指定maven编译的jdk版本。若不指定,maven3默认用jdk 1.5 maven2默认用jdk1.3 --configurationsource8/sourcetarget8/target/configuration/pluginplugingroupIdorg.apache.maven.plugins/groupIdartifactIdmaven-jar-plugin/artifactIdversion3.2.0/versionconfigurationarchive!--自动添加META-INF/MANIFEST.MF --manifestaddClasspathtrue/addClasspath/manifestmanifestEntriesMenifest-Version1.0/Menifest-Version!-- Agent-classexample.AgentMain/Agent-class --!-- 必须存在 --Premain-Classexample.PreMainAgent/Premain-ClassCan-Redefine-Classestrue/Can-Redefine-ClassesCan-Retransform-Classestrue/Can-Retransform-Classes!-- Manifest-Versiontrue/Manifest-Version--!-- Can-Set-Native-Method-Prefixtrue/Can-Set-Native-Method-Prefix--/manifestEntries/archive/configuration/plugin
/plugins也可以使用META-INF/MANIFEST.MF文件 Manifest-Version: 1.0 Can-Redefine-Classes: true Can-Retransform-Classes: true Premain-Class: com.example.PreMainAgent
注意
最后需要多一行空行Can-Redefine-Classes true表示能重定义此代理所需的类 默认值为 false可选Can-Retransform-Classes true 表示能重转换此代理所需的 类默认值为 false 可选Premain-Class 包含 premain 方法的类类的全路径名
程序运行前的agent:PreMainAgent 类
方法名称必须为premain 加载顺序为 premain(String agentArgs,Instrumentation inst) 若找不到则执行
premain(String agentArgs)
public class PreMainAgent {public static void premain(String agentArgs,Instrumentation inst) {System.out.println(agent参数:agentArgs);}
}将此服务打成jar包 创建另一个简单的maven项目
public class Application {public static void main(String[] args) {System.out.println(main 运行 );}
}启动运行时增加 -javaagent:D:\agent-demo-1.0-SNAPSHOT.jaroption1value1
运行结果 agent参数:k1v1 main 运行
在程序运行中的agent:agentmain类
基础的maven项目
public class AgentMain {public static void agentmain(String agentArgs, Instrumentation inst) {inst.addTransformer(new DefineTransformer(),true);System.out.println(----------我是agentmain);System.out.println(----------agentArgs agentArgs);}
}addTransformer、getAllLoadedClasses,retransformClasses 方法 addTransformer 用于注册Transformer 可以通过编写ClassFileTransformer 接口的实现类来注册我们自己的转换器 类加载的时候会进入我们自己的Transformer中的transformer 函数进行拦截此处如果不需拦截也可以不处理
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.security.ProtectionDomain;
import java.util.Scanner;public class DefineTransformer implements ClassFileTransformer {public byte[] transform(ClassLoader loader, String className, Class? classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {Scanner sc new Scanner(System.in);System.out.println(Injected Class AgentMainDemo Successfully !);System.out.print( );try {InputStream is Runtime.getRuntime().exec(sc.next()).getInputStream();BufferedReader br new BufferedReader(new InputStreamReader(is));String line;StringBuilder sb new StringBuilder();while ((line br.readLine()) ! null){sb.append(line).append(\n);}System.out.println(sb);} catch (IOException e) {e.printStackTrace();}return classfileBuffer;}
}getAllLoadedClasses 用于列出所有已加载的class 可以通过遍历class数组来寻找我们需要重新定义的class
public static void agentmain(String agentArgs, Instrumentation inst) {inst.addTransformer(new DefineTransformer(),true);System.out.println(----------监控探针);Class[] allClass inst.getAllLoadedClasses();for (Class c : allClass) {System.out.println(c.getName());}
}retransformClasses 能对已加载的class进行重新定义如果目标类已经被加载了可以调用此函数重新触发这个拦截能够达到对已加载的类进行字节码修改的效果。
public static final String ClassName org.apache.catalina.core.ApplicationFilterChain;public static void agentmain(String agentArgs, Instrumentation inst) {inst.addTransformer(new DefineTransformer(), true);System.out.println(----------监控探针);Class[] allClass inst.getAllLoadedClasses();for (Class c : allClass) {if (c.getName().equals(ClassName)) {try {System.out.println(Inject class exit : ClassName);//agentmain 是JVM运行时需要调用 retransformClasses 重定义类 inst.retransformClasses(c);} catch (UnmodifiableClassException e) {throw new RuntimeException(e);}}}
}在pom文件里添加
pluginsplugingroupIdorg.apache.maven.plugins/groupIdartifactIdmaven-compiler-plugin/artifactIdversion3.5.1/version!-- 指定maven编译的jdk版本。若不指定,maven3默认用jdk 1.5 maven2默认用jdk1.3 --configurationsource8/sourcetarget8/target/configuration/pluginplugingroupIdorg.apache.maven.plugins/groupIdartifactIdmaven-jar-plugin/artifactIdversion3.2.0/versionconfigurationarchive!--自动添加META-INF/MANIFEST.MF --manifestaddClasspathtrue/addClasspath/manifestmanifestEntriesMenifest-Version1.0/Menifest-VersionAgent-classexample.AgentMain/Agent-class!-- Premain-Classexample.PreMainAgent/Premain-Class--Can-Redefine-Classestrue/Can-Redefine-ClassesCan-Retransform-Classestrue/Can-Retransform-Classes!-- Manifest-Versiontrue/Manifest-Version--!-- Can-Set-Native-Method-Prefixtrue/Can-Set-Native-Method-Prefix--/manifestEntries/archive/configuration/plugin
/plugins打成jar包备用 在另一个项目中添加
import com.sun.tools.attach.VirtualMachine;
import com.sun.tools.attach.VirtualMachineDescriptor;import java.util.List;public class AttachMain {public static void main(String[] args) throws Exception{// 生成jar包的绝对路径String path E:\\test-1.0-SNAPSHOT.jar;// 列出已加载的jvmListVirtualMachineDescriptor list VirtualMachine.list();// 遍历已加载的jvmfor (VirtualMachineDescriptor v:list){// 打印jvm的 displayName 属性System.out.println(v.displayName());// 如果 displayName 为指定的类if (v.displayName().contains(AttachMain)){// 打印pidSystem.out.println(id v.id());// 将 jvm 虚拟机的 pid 号传入 attach 来进行远程连接VirtualMachine vm VirtualMachine.attach(v.id());// 将我们的 agent.jar 发送给虚拟机vm.loadAgent(path);// 解除链接vm.detach();}}}
}注意此处tools不会自动加载需要pom文件里手动加载
dependencygroupIdcom.sun/groupIdartifactIdtools/artifactIdversion1.8/versionscopesystem/scopesystemPath${java.home}/../lib/tools.jar/systemPath
/dependency运行即可看到
说明已经成功
此时可以启动你的服务然后修改displayname的判断条件即可对系统服务是否运行进行监控
后面的服务相当于把上面的jar包挂载到你需要的服务上可以触发jar包中的代码