当前位置: 首页 > 后端技术 > Java

JavaInstrument

时间:2023-04-01 15:22:45 Java

JVMTI什么是JVMTI?JVMToolInterface简称JVMTI,是一套对外接口。通过这组接口,可以实现获取虚拟机运行状态、线程分析、监控、调试、覆盖率分析等功能。什么是JVMTIAgent?为了使用JVMTI提供的对外接口,一般使用Agent来实现JVMTI提供的对外接口。JVMTIAgent类似于c语言中动态库的概念。实现方式在Java1.5之前,一个agent只能通过nativec/c++来实现。Java1.5之后提供了一个工具代理,也叫JPLISAgent(JavaProgrammingLanguageInstrumentationServicesAgent),专门用于Java。有两种方式启动代理。第一种是在jvm启动时通过指定agent程序的位置来启动agent。另一种方式是jvm已经在运行,并使用attach方法到目标进程。在java1.5中只支持jvm启动,在java1.6中支持attach方式启动。jvm的tool.jar中提供了VirtualMachine工具来帮助启动agent。Instrument什么是InstrumentInstrument为Java编程语言提供插入代码的服务。Instrumentation就是在方法中加入字节码来收集所使用的数据。由于这些更改是添加字节码,因此不会修改程序的状态或行为。示例包括代码监视器、分析器、覆盖分析器和事件记录器。Instrument只提供代码插入服务,将字节码添加到方法中。至于具体的字节码操作,则由字节码操作工具来实现。常见的字节码操作工具有:CGLIB、Javassist、ASM等获取Instrumentation实例并指定接收类要获取Instrumentation实例,首先要指定将Instrumentation实例传递给哪个类。有两种方法可以指定要传递给的类。第一种方式在配置文件resource\META_INF\MANIFEST.MF中指定。Manifest-Version:1.0Can-Redefine-Classes:trueCan-Retransform-Classes:truePremain-Class:com.lee.agent.PreMainAgentAgent-Class:com.lee.agent.PreMainAgent第二种方式是在pom文件中指定,本质上它还在配置MANIFEST.MF文件.agent.PreMainAgent指定接收方式当JVM以指定的agent类启动时,本例中Instrumentation实例为传递给代理类的premain方法;publicstaticvoidpremain(StringagentArgs,Instrumentationinst);publicstaticvoidpremain(StringagentArgs);JVM启动时,通过attach的方式指定代理类,此时Instrumentation实例被传递给代理类的agentmain方法。publicstaticvoidagentmain(StringagentArgs,Instrumentationinst);publicstaticvoidagentmain(StringagentArgs);示例代码总体流程图目标程序目标程序为要操作的程序,修改目标类TargetClass。publicclassDemo{publicstaticvoidmain(String[]args)throwsException{TargetClasstargetClass=newTargetClass();targetClass.targetMethod();}}publicclassTargetClass{publicStringtargetMethod(){System.out.println("执行测试方法");返回“返回”;}}AgentprogrampublicclassPreMainAgent{/***指定启动的agentjar包,Instrument实例会传给这个方法*/publicstaticvoidpremain(StringagentArgs,Instrumentationinst){customLogic(inst);}/***attach方法启动,Instrument实例将被传递给这个方法*/publicstaticvoidagentmain(StringagentArgs,Instrumentationinst){customLogic(inst);}privatestaticvoidcustomLogic(Instrumentationinst){inst.addTransformer(newMyClassTransformer(),true);}}classMyClassTransformer实现ClassFileTransformer{@Overridepublicbyte[]transform(ClassLoaderloader,StringclassName,ClassclassBeingRedefined,ProtectionDomainprotectionDomain,byte[]classfileBuffer){finalClassPoolclassPool=ClassPool.getDefault();}CtClass克拉兹;CtMethodct方法;尝试{if("com/lee/TargetClass".equals(className)){clazz=classPool.get("com.lee.TargetClass");ctMethod=clazz.getDeclaredMethod("targetMethod");ctMethod.insertBefore("System.out.println(\"****************\");");byte[]byteCode=clazz.toBytecode();clazz.分离();返回字节码;}}catch(Exceptione){e.printStackTrace();}返回空值;代理工程打包成jar包。启动agent.jar的方式有两种,在启动目标程序时指定agent的位置:-javaagent:jarpackagepath\Jagent.jarisstartedbyattaching//pidVirtualMachinevmstartedbyproject1=VirtualMachine.attach("1856");vm.loadAgent("jar包路径\Jagent.jar");

最新推荐
猜你喜欢