当前位置:   article > 正文

Java Agent基本简介和使用

javaagent用途

javaagent简介

javaagent是一种能够在不影响正常编译的情况下,修改字节码。java作为一种强类型的语言,不通过编译就不能能够进行jar包的生成。而有了javaagent技术,就可以在字节码这个层面对类和方法进行修改。同时,也可以把javaagent理解成一种代码注入的方式。但是这种注入比起spring的aop更加的优美。

javaagent主要作用

  • 可以在加载java文件之前做拦截把字节码做修改
  • 可以在运行期将已经加载的类的字节码做变更,但是这种情况下会有很多的限制,后面会详细说
    还有其他的一些小众的功能
  • 获取所有已经被加载过的类
  • 获取所有已经被初始化过了的类(执行过了clinit方法,是上面的一个子集)
  • 获取某个对象的大小
  • 将某个jar加入到bootstrapclasspath里作为高优先级被bootstrapClassloader加载
  • 将某个jar加入到classpath里供AppClassload去加载
  • 设置某些native方法的前缀,主要在查找native方法的时候做规则匹配

javaagent的使用

通过 -javaagent:xxx.jar=name=lisi&age=30 其中 xxx.jar 指定对应要加载的jar包的名字和路径,后面跟踪自己传入的参数即可
IDEA中传入参数可以参考下图


2020032-c8961cf9b2ba3ed7.jpg
CE3544A45245B229746E496D57FF29F1.jpg

新建agent

  1. package com.mergades.apm.javaagent;
  2. import java.lang.instrument.Instrumentation;
  3. /**
  4. * https://blog.csdn.net/fd2025/article/details/80280033
  5. */
  6. public class HelloAgent {
  7. public static void premain(String arg, Instrumentation instrumentation) {
  8. System.out.println("装载成功 方法 premain 参数:" + arg);
  9. }
  10. }

maven pom文件引入对应的jar包插件,指定mainfestEntries,指定自己的jar包路径

  1. <build>
  2. <plugins>
  3. <plugin>
  4. <groupId>org.apache.maven.plugins</groupId>
  5. <artifactId>maven-jar-plugin</artifactId>
  6. <version>2.6</version>
  7. <configuration>
  8. <archive>
  9. <manifestEntries>
  10. <Project-name>${project.name}</Project-name>
  11. <Project-version>${project.version}</Project-version>
  12. <Premain-Class>com.mergades.apm.javaagent.HelloAgent</Premain-Class>
  13. </manifestEntries>
  14. </archive>
  15. <skip>true</skip>
  16. </configuration>
  17. </plugin>
  18. <plugin>
  19. <groupId>org.apache.maven.plugins</groupId>
  20. <artifactId>maven-compiler-plugin</artifactId>
  21. <version>2.3.2</version>
  22. <configuration>
  23. <source>8</source>
  24. <target>8</target>
  25. <encoding>utf8</encoding>
  26. </configuration>
  27. </plugin>
  28. </plugins>
  29. </build>

mvn install 打包

运行引入

编写单元测试

  1. package com.mergades.apm.javaagent;
  2. public class HelloAgentTest {
  3. public static void main(String[] args) {
  4. System.err.println("TestHelloAgent main 方法");
  5. }
  6. }

单元测试run config引入自己的agent jar,直接运行,获取agent植入的输出结果。

  1. 装载成功 方法 premain 参数:name=lisi&age=30
  2. TestHelloAgent main 方法

Agentjar和普通jar的区别

运行时jaragent
入口方法名称Mainpremain
Maninfe.MF 主要参数Main-classPremain-Class
启动参数java -jar xxx.jar-javaagent:xxx.jar
执行顺序
是否独立启动

agent 代码植入

执行方法前加入代码,执行方法后加入代码

  1. package com.mergades.apm.classpool;
  2. import javassist.ClassPool;
  3. import javassist.CtClass;
  4. import javassist.CtMethod;
  5. import java.lang.instrument.ClassFileTransformer;
  6. import java.lang.instrument.IllegalClassFormatException;
  7. import java.security.ProtectionDomain;
  8. public class FirstAgent implements ClassFileTransformer {
  9. public final String injectedClassName = "com.mergades.apm.javaagent.HelloAgentTest";
  10. public final String methodName = "hello";
  11. @Override
  12. public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
  13. className = className.replace("/", ".");
  14. if (className.equals(injectedClassName)) {
  15. CtClass ctclass;
  16. Long start = System.nanoTime();
  17. try {
  18. ctclass = ClassPool.getDefault().get(className);// 使用全称,用于取得字节码类<使用javassist>
  19. CtMethod ctmethod = ctclass.getDeclaredMethod(methodName);// 得到这方法实例
  20. ctmethod.insertBefore("System.out.println(11111111);");
  21. return ctclass.toBytecode();
  22. } catch (Exception e) {
  23. System.out.println(e.getMessage());
  24. e.printStackTrace();
  25. } finally {
  26. System.out.println("className took:" + (System.nanoTime() - start));
  27. }
  28. }
  29. return null;
  30. }
  31. }
  1. package com.mergades.apm.javaagent;
  2. import com.mergades.apm.classpool.FirstAgent;
  3. import java.lang.instrument.Instrumentation;
  4. /**
  5. * https://blog.csdn.net/fd2025/article/details/80280033
  6. */
  7. public class HelloAgent {
  8. public static void premain(String arg, Instrumentation instrumentation) {
  9. System.out.println("premain 装载成功 方法 premain 参数:" + arg);
  10. // 添加Transformer
  11. instrumentation.addTransformer(new FirstAgent());
  12. }
  13. }

单元测试

  1. package com.mergades.apm.javaagent;
  2. public class HelloAgentTest {
  3. public static void main(String[] args) {
  4. System.err.println("TestHelloAgent main 方法");
  5. hello();
  6. }
  7. public static void hello() {
  8. try {
  9. Thread.sleep(200);
  10. } catch (InterruptedException e) {
  11. e.printStackTrace();
  12. }
  13. System.out.println("HelloAgentTest hello() output");
  14. }
  15. }

输出结果

  1. premain 装载成功 方法 premain 参数:name=lisi&age=30
  2. className tooks:201016907
  3. TestHelloAgent main 方法
  4. 11111111
  5. HelloAgentTest hello() output
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/349081
推荐阅读
相关标签
  

闽ICP备14008679号