当前位置:   article > 正文

Java探针技术--javaAgent

-javaagent

一.JavaAgent概述

1.JavaAgent简述

        使用Skywalking的时候,并没有修改程序中任何一行 Java 代码,这里便使用到了Java Agent 技术。

        我们平时用过的很多工具都是基于java Agent来实现的,例如:

        <1> 热部署工具JRebel

         <2> springboot的热部署插件

        <3>  各种线上诊断工具(btrace, greys)

        <4>  阿里开源的arthas等等

 2.Agent分为两种

        (1)在主程序之前运行的Agent

        (2)在主程序之后运行的Agent

二..JavaAgent入门

1.premain(主程序之前运行的Agent)

(1)说明

        在实际使用过程中,javaagent是java命令的一个参数。通过java 命令启动我们的应用程序的时候,可通过参数 -javaagent 指定一个 jar 包(也就是我们的代理agent),能够实现在我们应用程序的主程序运行之前来执行我们指定jar 包中的特定方法,在该方法中我们能够实现动态增强Class等相关功能,并且该 jar包有2个要求:

        <1> 这个 jar 包的 META-INF/MANIFEST.MF 文件必须指定 Premain-Class 项,该选项指定的是一个类的全路径.

        <2> Premain-Class 指定的那个类必须实现 premain() 方法。

        META-INF/MANIFEST.MF文件内容如下

  1. Manifest-Version: 1.0
  2. Can-Redefine-Classes: true
  3. Can-Retransform-Classes: true
  4. Premain-Class: com.itheima.PreMainAgent

注意:

        <1> 最后需要多一行空行

        <2> Can-Redefine-Classes :true表示能重定义此代理所需的类, 默认值为 false(可选)

        <3> Can-Retransform-Classes :true 表示能重转换此代理所需的 类,默认值为 false (可选)

        <4> Premain-Class :包含 premain 方法的类(类的全路径名)

(2)premain案例demo

<1> 创建java-agent工程,pom.xml配置如下

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5. <modelVersion>4.0.0</modelVersion>
  6. <groupId>com.itheima</groupId>
  7. <artifactId>agent-demo</artifactId>
  8. <version>1.0-SNAPSHOT</version>
  9. <properties>
  10. <maven.compiler.source>8</maven.compiler.source>
  11. <maven.compiler.target>8</maven.compiler.target>
  12. </properties>
  13. <dependencies>
  14. <dependency>
  15. <groupId>net.bytebuddy</groupId>
  16. <artifactId>byte-buddy</artifactId>
  17. <version>1.9.2</version>
  18. </dependency>
  19. <dependency>
  20. <groupId>net.bytebuddy</groupId>
  21. <artifactId>byte-buddy-agent</artifactId>
  22. <version>1.9.2</version>
  23. </dependency>
  24. </dependencies>
  25. <build>
  26. <plugins>
  27. <plugin>
  28. <artifactId>maven-assembly-plugin</artifactId>
  29. <configuration>
  30. <appendAssemblyId>false</appendAssemblyId>
  31. <descriptorRefs>
  32. <descriptorRef>jar-with-dependencies</descriptorRef>
  33. </descriptorRefs>
  34. <archive> <!--自动添加META-INF/MANIFEST.MF -->
  35. <manifest>
  36. <!-- 添加 mplementation-*和Specification-*配置项-->
  37. <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
  38. <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
  39. </manifest>
  40. <manifestEntries>
  41. <!--指定premain方法所在的类-->
  42. <Premain-Class>com.itheima.agent.PreMainAgent</Premain-Class>
  43. <Can-Redefine-Classes>true</Can-Redefine-Classes>
  44. <Can-Retransform-Classes>true</Can-Retransform-Classes>
  45. </manifestEntries>
  46. </archive>
  47. </configuration>
  48. <executions>
  49. <execution>
  50. <id>make-assembly</id>
  51. <phase>package</phase>
  52. <goals>
  53. <goal>single</goal>
  54. </goals>
  55. </execution>
  56. </executions>
  57. </plugin>
  58. </plugins>
  59. </build>
  60. </project>

<2>编写一个java agent程序

  1. public class PreMainAgent {
  2. public static void premain(String agentArgs,Instrumentation inst) {
  3. System.out.println("我的agent程序跑起来啦!");
  4. System.out.println("收到的agent参数是:"+agentArgs);
  5. }
  6. }

<3>对java-agent工程打包得到 java-agent-1.0-SNAPSHOT.jar

<4>创建 agent-test 项目,编写一个类: com.itheima.Application

  1. public class Application {
  2. public static void main(String[] args) {
  3. System.out.println("main 函数 运行了 ");
  4. }
  5. }

<5>启动运行,添加 -javaagent 参数

-javaagent:D:\develop\javaagent\agent-demo-1.0-SNAPSHOT.jar=option1=value1,option2=value2

<6>运行结果

  1. 我的agent程序跑起来啦!
  2. 收到的agent参数是:k1=v1,k2=v2
  3. main 函数 运行了

<7>总结

  1. 这种agent JVM 会先执行 premain 方法,大部分类加载都会通过该方法,
  2. 注意:是大部分,不是所有。当然,遗漏的主要是系统类,因为很多系统类
  3. 先于 agent 执行,而用户类的加载肯定是会被拦截的。也就是说,这个方法
  4. 是在 main 方法启动前拦截大部分类的加载活动,既然可以拦截类的加载,
  5. 那么就可以去做重写类这样的操作,结合第三方的字节码编译工具,比如ASM,
  6. bytebuddy,javassist,cglib等等来改写实现类。
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/317947
推荐阅读
相关标签
  

闽ICP备14008679号