一:认识一下 JavaAgent(实操)
JavaAgent
1.0 先看几个面试题:
- 怎么获取某个对象的大小?
- 运行期将已经加载的类的字节码能做变更吗,怎么做?有什么限制?
- 如何获取所有已经被加载过的类?
- 怎么在加载java文件之前做拦截把字节码做修改?
- 如何获取所有已经被初始化过了的类(clinit后的方法)
- 如何设置某些native方法的前缀?
- 如何在查找native方法的时候做规则匹配?
- 如何将某个jar加入到bootstrapclasspath 里作为高优先级被bootstrapClassloader 加载?
- AppClassloader怎么去加载某个加入到 classpath 里的 jar?
我:…(#$%^&*)
1.1 先从来源说起
JavaAgent 是JDK 1.5 以后引入的,也可以叫做Java代理。
JavaAgent 是运行在 main方法之前的拦截器,它内定的方法名叫 premain ,也就是说先执行 premain 方法然后再执行 main 方法。
主要功能如下:
- 看问题 1.0
按照加载时机可以分为两种:
- 进程启动前
- 进程启动后
1.2 如何实操?
准备工作:
- 电脑一台、带键盘鼠标显示器,能通电能开机,内存512M,一核CPU,差不多就行
- 安装 jdk(1.8) ,安装 IDEA(2021.2.4),安装 maven
实施步骤:
-
首先创建一个 Java Aganet 的 maven 项目,步骤如下:
打开 IDEA:

新建项目:




走到这一步的小伙伴就可以编写具体的 JavaAgent 的代码了。


具体代码:
package com.carrot.sec;import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.lang.instrument.Instrumentation;
import java.security.ProtectionDomain;public class MyAgent {public static void premain(String arg, Instrumentation instrumentation){System.err.println("MyAgent 开始执行了! , 参数是 " + arg);//注册我们的函数instrumentation.addTransformer(new ClassFileTransformer() {public byte[] transform(ClassLoader loader,String className,Class<?> classBeingRedefined,ProtectionDomain protectionDomain,byte[] classfileBuffer) throws IllegalClassFormatException {System.out.println("加载的类名字是: " + className);return classfileBuffer;}});}}
写好了就打包一个 java 的 jar 包。
pom文件增加以下内容:
<build><plugins><plugin><groupId>org.apache.maven.pluginsgroupId><artifactId>maven-compiler-pluginartifactId><version>3.1version><configuration><source>8source><target>8target>configuration>plugin><plugin><groupId>org.apache.maven.pluginsgroupId><artifactId>maven-jar-pluginartifactId><configuration><archive><manifestFile>src/main/resources/META-INF/MANIFEST.MFmanifestFile>archive>configuration>plugin>plugins>build>
执行 maven 打包命令:


mvn clean package -U -DMaven.test.skip=true

出现这个错误,不要慌,去 resources 下手动创建 pom 文件里面指定的目录:src/main/resources/META-INF/MANIFEST.MF




META-INF/MANIFEST.MF 的内容:
Manifest-Version: 1.0
Premain-Class: com.carrot.sec.MyAgent
Can-Redefine-Classes: true
Can-Retransform-Classes: true
| 属性 | 说明 | 是否必填 | 默认值 |
|---|---|---|---|
| Premain-Class | 包含premain方法的类 | 依赖启动方式 | 无 |
| Agent-Class | 包含agentmain方法的类 | 依赖启动方式 | 无 |
| Boot-Class-Path | 启动类加载器搜索路径 | 否 | 无 |
| Can-Redefine-Classis | 是否可以重定义代理所需的类 | 否 | false |
| Can-Retransform-Classis | 是否能够重新转换此代理所需的类 | 否 | false |
| Can-Set-Native-Method-Prefix | 是否能够设置此代理所需的本机方法前缀 | 否 | false |
再次打包就可以了。。。

找到 jar 包,检查里面的内容,如果不对就修改一下。





没啥问题就过了。。。
- 再建一个普通的项目,我这边比较懒直接建了个 Spring boot 项目。
- 步骤如下:













IDEA中的VM命令
-javaagent:D:\local-project\FirstAgent\target\FirstAgent-1.0-SNAPSHOT.jar
这些工作做完了之后就可以启动我们的 Spring Boot 项目了。

假如你想用命令来启动,也是可以做到的:
-
把 Spring Boot 项目打包,和 MyAgent 的打包方式是一样的~~~
-
找到 Spring Boot 的 jar 包的位置,也找到 MyAgent 的位置。



-
执行命令:
java -javaagent:D:\local-project\FirstAgent\target\FirstAgent-1.0-SNAPSHOT.jar -jar demo-0.0.1-SNAPSHOT.jar
更多的用法或者用途,我们一起发现一起创造!
比如:
- 怎么获取某个对象的大小?
- 运行期将已经加载的类的字节码能做变更吗,怎么做?有什么限制?
- 如何获取所有已经被加载过的类?
- 怎么在加载java文件之前做拦截把字节码做修改?
- 如何获取所有已经被初始化过了的类(clinit后的方法)
- 如何设置某些native方法的前缀?
- 如何在查找native方法的时候做规则匹配?
- 如何将某个jar加入到bootstrapclasspath 里作为高优先级被bootstrapClassloader 加载?
- AppClassloader怎么去加载某个加入到 classpath 里的 jar?
这些案例会抽时间逐一做出解答。
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
