Java字节码3-使用ByteBuddy实现一个Java-Agent
来源:互联网 发布:mac world破解版 编辑:程序博客网 时间:2024/06/13 19:16
Java字节码系列
Java字节码1-Agent简单上手
Java字节码2-instrument初体验
Java字节码3-使用ByteBuddy实现一个Java-Agent
Java字节码4-使用Java-Agent实现一个JVM监控工具
一、概述
在前面两节中,我们实现了Agent,但是其无论在使用方式和功能上面都有一定的局限性。本文我们借助字节码工具ByteBuddy,写出高级的Agent。
ByteBuddy不仅仅是为了生成Java-Agent,它提供的API甚至可以改变重写一个Java类,本文我们使用其API实现和第二节一样的功能,给目标类中的函数统计其调用耗时。
二、实现
1、修改pom.xml
本节和上节的不同点,主要有两个。一个是引入ByteBuddy的依赖,另一个是需要将ByteBuddy的包通过shade打入到Agent中。下面只截取关键代码:
<dependency> <groupId>net.bytebuddy</groupId> <artifactId>byte-buddy</artifactId> <version>1.5.7</version></dependency><dependency> <groupId>net.bytebuddy</groupId> <artifactId>byte-buddy-agent</artifactId> <version>1.5.7</version></dependency>
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> </execution> </executions> <configuration> <artifactSet> <includes> <include>javassist:javassist:jar:</include> <include>net.bytebuddy:byte-buddy:jar:</include> <include>net.bytebuddy:byte-buddy-agent:jar:</include> </includes> </artifactSet> </configuration> </plugin>
2、实现一个Agent
与之前相同的是,这里仍然是在premain
处进行处理。通过AgentBuilder
方法,生成一个Agent。这里有两点需要特别说明:其一是在AgentBuilder.type
处,这里可以指定需要拦截的类;其二是在builder.method
处,这里可以指定需要拦截的方法。当然其API支持各种isStatic、isPublic
等等一系列方式。
public class MyAgent { public static void premain(String agentArgs, Instrumentation inst) { System.out.println("this is an perform monitor agent."); AgentBuilder.Transformer transformer = new AgentBuilder.Transformer() { @Override public DynamicType.Builder<?> transform(DynamicType.Builder<?> builder, TypeDescription typeDescription, ClassLoader classLoader) { return builder .method(ElementMatchers.<MethodDescription>any()) // 拦截任意方法 .intercept(MethodDelegation.to(TimeInterceptor.class)); // 委托 } }; AgentBuilder.Listener listener = new AgentBuilder.Listener() { @Override public void onTransformation(TypeDescription typeDescription, ClassLoader classLoader, JavaModule module, DynamicType dynamicType) {} @Override public void onIgnored(TypeDescription typeDescription, ClassLoader classLoader, JavaModule module) { } @Override public void onError(String typeName, ClassLoader classLoader, JavaModule module, Throwable throwable) { } @Override public void onComplete(String typeName, ClassLoader classLoader, JavaModule module) { } }; new AgentBuilder .Default() .type(ElementMatchers.nameStartsWith("com.example.demo")) // 指定需要拦截的类 .transform(transformer) .with(listener) .installOn(inst); }}
3、实现一个用来委托的Interceptor
在上一步实现Transformer
的过程中,委托了一个TimeInterceptor.class
。下面是其实现方式,整个的try
语句是原有的代码执行,我们在之前打了时间戳,并在其结束后,计算并打印了其调用耗时。
public class TimeInterceptor { @RuntimeType public static Object intercept(@Origin Method method, @SuperCall Callable<?> callable) throws Exception { long start = System.currentTimeMillis(); try { // 原有函数执行 return callable.call(); } finally { System.out.println(method + ": took " + (System.currentTimeMillis() - start) + "ms"); } }}
三、运行
这里需要注意的是,我们定义的包路径要和Agent中定义的相同,否则Agent无法Hook到这个类及其方法。
package com.example.demo;public class AgentTest { private void fun1() throws Exception { System.out.println("this is fun 1."); Thread.sleep(500); } private void fun2() throws Exception { System.out.println("this is fun 2."); Thread.sleep(500); } public static void main(String[] args) throws Exception { AgentTest test = new AgentTest(); test.fun1(); test.fun2(); }}
结果:
this is an perform monitor agent.this is fun 1.private void com.example.demo.AgentTest.fun1() throws java.lang.Exception: took 501msthis is fun 2.private void com.example.demo.AgentTest.fun2() throws java.lang.Exception: took 500mspublic static void com.example.demo.AgentTest.main(java.lang.String[]) throws java.lang.Exception: took 1001ms
可以看到,我们的Agent成功Hook并增强了其调用方法。
- Java字节码3-使用ByteBuddy实现一个Java-Agent
- Java字节码4-使用Java-Agent实现一个JVM监控工具
- 使用JVM TI技术插装字节码,实现Java代码执行控监Agent
- Java字节码1-Agent简单上手
- Java使用agent实现main方法之前
- java.lang.NoClassDefFoundError: net/bytebuddy/matcher/ElementMatchers org/objenesis/ObjenesisStd
- Java使用字节流复制一个文件夹
- 使用ASM操作Java字节码,实现AOP原理
- 使用ASM操作Java字节码,实现AOP原理
- 使用ASM操作Java字节码,实现AOP原理
- java agent
- Java agent实现JVM exception 统计
- JAVA Agent的原理和使用
- java.lang.Instrument 代理Agent使用
- java字节码增强技术实现过程
- 使用javap反编译Java字节码文件
- 使用javap反编译Java字节码文件
- 使用Java字节流的缓冲区实现图片加密
- java 多态
- O
- 用递归的方法把一个无符号整数的每一位数字单独写出来,并且计算出每一位加起来的和。
- 性能测试的一些行话,郭芙大话性能测试
- Centos7安装YouCompleteMe(一)
- Java字节码3-使用ByteBuddy实现一个Java-Agent
- 理解Java类加载的步骤
- 模板库(数据结构)
- 【Ubuntu】在终端内使用screenFetch(显示版本信息)
- Python实现指定排序函数进行排序
- Android App冷启动优化
- 软件工程(C语言实践篇)学习心得总结
- 把字符串转换成整数
- 上下界网络流