言归主题,在确定了需求以及大致思路后,在进行准备的过程中,发现了一个javaagent的东西,可以有效的完成我们的需求。
什么是javaagent呢?
顾名思义,javaagent是一个对java进行代理的东西,找到一段我觉得较准确的描述
引用
javaagent是一种能够在不影响正常编译的情况下,修改字节码。java作为一种强类型的语言,不通过编译就不能能够进行jar包的生成。而有了javaagent技术,就可以在字节码这个层面对类和方法进行修改。同时,也可以把javaagent理解成一种代码注入的方式。但是这种注入比起spring的aop更加的优美。
在我简单操作之后,对这个东西的理解就是,他是一个字节码层面的类的加强器,即可以在不改变类的情况下,附加一些我们需要增加的功能。
如何使用javaagnet呢,有两个条件,第一,实现一个premain方法,第二在打包时,明确实现premain方法的 类。
在将自定义的agent进行打包后,可以看到jar包的内容为
Manifest-Version: 1.0 Premain-Class: ClassAgent Built-By: . Created-By: Apache Maven 3.5.0 Build-Jdk: 1.8.0_111
即有指定preclass的类,这就可以作为javaagent的工具包了。
具体使用方法就是,在执行我们的代码是,在启动参数上添加 -javaagent:{path-to-our-agent.jar},替换进我们agent工具包的地址就行,这样我们就可以看到在执行真正代码前,先执行了我们的premain方法,这也就是为什么叫pre-main了^-^
太迟了,随便写了一个demo实验了一下
public class ClassAgent { public static void premain(String agentOps, Instrumentation instrumentation) { System.out.println("---------start agent-------------"); System.out.println(agentOps); instrumentation.addTransformer(new ClassTransformer()); } }
public class ClassTransformer implements ClassFileTransformer { public byte[] transform(ClassLoader loader, String className, Class> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException { public class ClassTransformer implements ClassFileTransformer { public byte[] transform(ClassLoader loader, String className, Class> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException { System.out.println(className.replace('/','.')); return new byte[0]; } } return new byte[0]; } }
再在pom.xml文件里注册premain的class
org.apache.maven.plugins maven-jar-plugin 3.0.2 ClassAgent
最后,将这个项目打包,并将jar包位置作为参数,传入实际执行代码的启动参数中,并启动
看到console输出
离目标前进了一小步,睡觉