闲聊
最近在配置skywalking
的过程中发现了-javaagent:
这个配置,这里做一个简单的学习
什么是JavaAgent
网上似乎没有直接的文档介绍这个,只找了instrument包的相关文档,其内容页。其中的内容也都是介绍javaagent相关。
instrument包下核心就是字节码增强,此包下有2个核心接口ClassFileTransformer
,Instrumentation
-
ClassFileTransformer
:An agent provides an implementation of this interface in order to transform class files. -
ClassFileTransformer
:代理需要实现这个接口,并对class文件转化(增强) -
Instrumentation
:This class provides services needed to instrument Java programming language code. -
Instrumentation
:Instrumentation 为代码增强提供了必要的服务和功能。
有什么用及怎么用
有什么用
代码增强可以用于监控代理、分析器、覆盖分析器和事件记录器。
怎么用
上面介绍了这么多编码过程,如果想要能使用,则需要打成jar包,具体使用需要通过-javaagent
来让代码运行。总算知道为啥没有文档了,-javaagent
主要是用来让代理生效的,核心是instrument包
。
如果伴随jar包启动,需要创建premain方法,并在MANIFEST.MF
中指定Premain-Class: com.mountain.monk.MyAgent
如果是在启动后,再进行代理,则需要创建agentmain方法,并在MANIFEST.MF
中指定Agent-Class: com.mountain.monk.MyAgent
实现一个计算函数执行时间的功能
- 随便创建一个类,创建premain方法,此处我使用了
javassist
来生成字节码
public class MyAgent {public static void premain(String agentArgs, Instrumentation inst) {inst.addTransformer(new TimeTransformer(),true);}public static class TimeTransformer implements ClassFileTransformer {@Overridepublic byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {// 这里我们限制下,只针对目标包下进行耗时统计if (!className.startsWith("com/mountain/monk/")) {return classfileBuffer;}CtClass cl = null;try {ClassPool classPool = ClassPool.getDefault();cl = classPool.makeClass(new ByteArrayInputStream(classfileBuffer));for (CtMethod method : cl.getDeclaredMethods()) {method.addLocalVariable("start", CtClass.longType);method.insertBefore("start = System.currentTimeMillis(); ");method.insertAfter("System.out.println(\"「monk」methodName:" + method.getName() + ", cost: \" + (System" +".currentTimeMillis() - start));");}return cl.toBytecode();} catch (Exception e) {System.err.println("Error transforming class: " + className);e.printStackTrace();}return classfileBuffer;}}
}
- 创建
MANIFEST.MF
,注意最后要空一行
Premain-Class: com.mountain.monk.MyAgent
Can-Redefine-Calsses: true
Can-Retransform-Classes: true
- 配置maven,注意:我这里需要把依赖打包进去
<build><plugins><plugin><artifactId>maven-assembly-plugin</artifactId><configuration><archive><manifestFile>src/main/resources/META-INF/MANIFEST.MF</manifestFile></archive><descriptorRefs><descriptorRef>jar-with-dependencies</descriptorRef></descriptorRefs></configuration><executions><execution><id>make-assembly</id><phase>package</phase><goals><goal>single</goal></goals></execution></executions></plugin></plugins></build>
- 配置Idea启动参数
-javaagent:/Users/chenhui/learn/monk_note/self_agent/target/self_agent-1.0-SNAPSHOT-jar-with-dependencies.jar
- 随便找一个代码启动
- 代码地址:https://github.com/Nortyr/monk_note/tree/main/self_agent
- 参考链接:https://docs.oracle.com/javase/6/docs/api/java/lang/instrument/package-summary.html