Java字节码instrument研究
MyAgent项目
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.book.MyAgent</groupId><artifactId>MyAgent</artifactId><version>1.0</version><dependencies><dependency><groupId>javassist</groupId><artifactId>javassist</artifactId><version>3.12.1.GA</version></dependency><dependency><groupId>org.ow2.asm</groupId><artifactId>asm-all</artifactId><version>5.1</version></dependency><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></dependencies><build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><configuration><source>1.8</source><target>1.8</target></configuration></plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-source-plugin</artifactId><version>3.0.1</version><executions><execution><id>attach-sources</id><phase>verify</phase><goals><goal>jar-no-fork</goal></goals></execution></executions></plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-assembly-plugin</artifactId><version>2.6</version><configuration><descriptorRefs><descriptorRef>jar-with-dependencies</descriptorRef></descriptorRefs><archive><manifestFile>src/main/resources/META-INF/MANIFEST.MF</manifestFile></archive></configuration><executions><execution><id>assemble-all</id><phase>package</phase><goals><goal>single</goal></goals></execution></executions></plugin><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></plugins><resources><resource><directory>${basedir}/src/main/resources</directory></resource><resource><directory>${basedir}/src/main/java</directory></resource></resources></build>
</project>
AgentTime类
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.Instrumentation;public class AgentTime {public static void premain(String agentArgs, Instrumentation inst) {System.out.println("监控耗时 >>>");// 添加 TransformerClassFileTransformer transformer = new PerformMonitorTransformer();inst.addTransformer(transformer);System.out.println("监控耗时 <<<");}
}
PerformMonitorTransformer类
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.security.ProtectionDomain;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtBehavior;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.expr.ExprEditor;
import javassist.expr.MethodCall;public class PerformMonitorTransformer implements ClassFileTransformer {private static final Set<String> classNameSet = new HashSet<>();static {classNameSet.add("com.book.test.TestTime");}@Overridepublic byte[] transform(ClassLoader loader,String className,Class<?> classBeingRedefined,ProtectionDomain protectionDomain,byte[] classfileBuffer) throws IllegalClassFormatException {//System.out.println("监控耗时 >>>1");try {String currentClassName = className.replaceAll("/", ".");if (!classNameSet.contains(currentClassName)) { // 仅仅提升Set中含有的类return null;}System.out.println("transform: [" + currentClassName + "]");CtClass ctClass = ClassPool.getDefault().get(currentClassName);CtBehavior[] methods = ctClass.getDeclaredBehaviors();for (CtBehavior method : methods) {System.out.println("method: [" + method + "]");enhanceMethod(method);}CtMethod m = ctClass.getDeclaredMethod("fun1");m.insertBefore("{ System.out.println($1); System.out.println($2); }"); return ctClass.toBytecode();} catch (Exception e) {e.printStackTrace();}return null;}private void enhanceMethod(CtBehavior method) throws Exception {if (method.isEmpty()) {return;}String methodName = method.getName();if (methodName.equalsIgnoreCase("main")) { // 不提升main方法return;}CtClass[] prams = method.getParameterTypes();if (prams.length > 0) {method.insertBefore("{ System.out.println($1);System.out.println($2); }");}final StringBuilder source = new StringBuilder();if (methodName.equalsIgnoreCase("fun3")) { // 修改fun3方法source.append("{").append("System.out.println(\"方法三真的被替换了\");").append("\n").append("}");} else {source.append("{").append("long start = System.nanoTime();\n") // 前置增强: 打入时间戳.append("$_ = $proceed($$);\n") // 保留原有的代码处理逻辑 .append("System.out.print(\"method:[" + methodName + ">>>]\");").append("\n").append("System.out.println(\" cost:[\" +(System.nanoTime() -start)+ \"ns]\");") // 后置增强.append("}");}ExprEditor editor = new ExprEditor() {@Overridepublic void edit(MethodCall methodCall) throws CannotCompileException {methodCall.replace(source.toString());}};method.instrument(editor);}
}
被增强的项目:
TestAgent
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.book</groupId><artifactId>TestAgent</artifactId><version>1.0-SNAPSHOT</version><packaging>jar</packaging><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><maven.compiler.source>1.8</maven.compiler.source><maven.compiler.target>1.8</maven.compiler.target></properties><build><plugins><plugin> <artifactId>maven-assembly-plugin</artifactId> <configuration> <appendAssemblyId>false</appendAssemblyId> <descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> <archive> <manifest> <mainClass>com.book.test.TestTime</mainClass> </manifest> </archive></configuration> <executions> <execution> <id>make-assembly</id> <phase>package</phase> <goals> <goal>assembly</goal> </goals> </execution> </executions> </plugin> </plugins></build>
</project>
TestTime类
public class TestTime {private int fun1(int a,int b) {System.out.println("\n方法一开始>>>");return a+b;}private void fun2() {System.out.println("\n方法二开始>>>");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace(); }System.out.println("方法二结束<<<");}private void fun3() {System.out.println("方法三会被干掉么?"); }public static void main(String[] args) {TestTime test = new TestTime();test.fun1(2,3);test.fun2();test.fun3();}
}
运行:
java -javaagent:E:\worktest\MyAgent\target\MyAgent-1.0-jar-with-dependencies.jar -jar E:\worktest\TestAgent\target\TestAgent-1.0-SNAPSHOT.jar com.book.test.TestTime
参考:https://blog.csdn.net/f59130/article/details/78481594
Javassist 使用指南(三)
相关文章:

怎样保持良好的心态
有一位朋友有一次气冲冲的跟我说:“气死我了!我刚刚发现我一位员工出了错,令产品出现了质量的问题,我修理了他一顿。。。 我问:”你认为你的生产流程里面可能一点错误都没有吗?“ 他说:”应该不…

web编程速度大比拼(nodejs go python)(非专业对比)
C10K问题的解决,涌现出一大批新框架,或者新语言,那么问题来了:到底谁最快呢?非专业程序猿来个非专业对比。 比较程序:输出Hello World! 测试程序:siege –c 100 –r 100 –b 例子包括࿱…

linux邮件服务
邮件服务要求:l 能够构建完整的邮件系统 能够正确设置DNS邮件服务器记录 l 能够配置sendmail服务器 设置客户端软件使用邮件服务器 准备工作: l 主机名:srv.benet.com /etc/sysconfig/network <永久的> l 域名 正向区域 bt.com完成NDS的…
MaskFlownet:基于可学习遮挡掩模的非对称特征匹配丨CVPR 2020
来源 | 微软研究院AI头条(ID: MSRAsia)编者按:在光流预测任务中,形变带来的歧义与无效信息会干扰特征匹配的结果。在这篇 CVPR 2020 Oral 论文中,微软亚洲研究院提出了一种可学习遮挡掩模的非对称特征匹配模块 &#x…

GDB调试--以汇编语言为例
#rpm -qa |grep gdb 下载: 安装 #tar -zxvf #./configure #make 使用GDB 以汇编语言调试为例 汇编语言实现CPUID指令 CPUID cpuid是Intel Pentinum以上级CPU内置的一个指令(486级以下的CPU不支持),他用于识别某一类型…

汇编语言系统调用过程
以printf为例,详细解析一个简单的printf调用里头,系统究竟做了什么,各寄存器究竟如何变化。 如何在汇编调用glibc的函数?其实也很简单,根据c convention call的规则,参数反向压栈,call…

switch语句中在case块里声明变量会遇到提示“Expected expression before...的问题
switch语句中在case块里声明变量会遇到提示“Expected expression before..."的问题 例如在如下代码中 1case constant:2 int i 1;3 int j 2;4 self.sum i j;5 break;GCC在case语句之后的第一行中声明变量时遇到问题。 这时需要在case块两端添加花括号&am…
帮AI体检看病一条龙服务,阿里发布“AI安全诊断大师”
如同一些出生免疫力就有缺陷的人一样,AI也存在免疫力缺陷。基于从源头打造安全免疫力的新一代安全架构理念,最近,阿里安全研究发布了一项核心技术“AI安全诊断大师”,可对AI模型全面体检,“看诊开方”,让AI…

Spring学习总结(7)——applicationContext.xml 配置文详解
web.xml中classpath:和classpath*: 有什么区别? classpath:只会到你的class路径中查找找文件; classpath*:不仅包含class路径,还包括jar文件中(class路径)进行查找. 存放位置: 1:src下面 需要在web.xml中定义如下&…

GDB查看栈信息
栈:是程序存放数据内存区域之一,特点是LIFO(后进先出)。 PUSH:入栈 POP:出战 使用场景: 1.保存动态分配的自动变量使用栈 2.函数调用时,用栈传递函数参数,半寸返回地址…

数据库学习之路
今天迎来入冬的第二场雪,闲来无事就整理了下总结下工作以来所有数据库方面的书籍和资料,发现了不少,很多已经读过或者正在读的书籍,oracle真的很强大,直到现在发现才入门的水平,当然很多书读一遍是不行的&a…
为什么铺天盖地都是Python的广告?
最近,知乎关于Python有一个热议问题: 甚至在抖音上,笔者有一次还看到Python占领了热搜!应该有很多不懂技术的吃瓜群众也被Python的热度炒懵了……但是,Python真的值得学吗?真的值得花这么多钱去学吗&#x…

python3正则表达式符号和用法
转载于:https://www.cnblogs.com/wumac/p/5441322.html
从寄存器看I386和x64位中函数调用中参数传递
x86_64基本使用寄存器存储函数参数,寄存器不够才入栈; 而i386将所有参数保存在栈上,通过gcc的扩展功能__attribute__((regparm()))即可实现部分参数的寄存器传递。 调试语法: --《深入理解计算机系统(原书第2版)》 代码 #incl…

转:去掉Flex4生成的SWF加载时的进度条
方法一: <?xml version"1.0" encoding"utf-8"?> <s:Application xmlns:fx"http://ns.adobe.com/mxml/2009" xmlns:s"library://ns.adobe.com/flex/spark" xmlns:mx"library://ns.adobe.com/f…
饿了么交易系统5年演化史
作者 | 挽晴来源 | 阿里巴巴中间件(ID:Aliware_2018)个人简介:2014年12月加入饿了么,当时参与后台系统的研发(WalisJavis>Walle),主要面向客服和BD。2015年5月开始接触订单系统的研发,7月负责订单研发组…

Python迁移MySQL数据到MongoDB脚本
MongoDB是一个文档数据库,在存储小文件方面存在天然优势。随着业务求的变化,需要将线上MySQL数据库中的行记录,导入到MongoDB中文档记录。 一、场景:线上MySQL数据库某表迁移到MongoDB,字段无变化。 二、Python模块&am…

使用valgrind分析C程序调用线路图
Valgrind可以检测内存泄漏和内存违例,但是用Valgrind生成的日志信息结合kcachegrind就可以查看C程序的执行线路图,调用时间,是做性能优化和查看代码的非常好的工具。 1.下载安装 Valgrind 安装 到www.valgrind.org下载最新版valgrind # wg…

纯CSS实现蓝色圆角下拉菜单
代码简介: 这个菜单没有使用任何的图片,完全是用CSS实现的,包括圆角效果也同样是,而且还考虑了多浏览器的兼容性,可以说非常不错,既兼容性好,又外观漂亮,下拉导航菜单目前比较流行&a…
生产型机器学习已经没那么困难了?
作者 | Caleb Kaiser译者 | 香槟超新星出品 | CSDN(ID:CSDNnews)封面图源自视觉中国在软件工程的诸多领域内,生产用例是相当标准化的。以Web开发为例,要在Web应用中实现身份认证,你不会去创造一个数据库,自…

poj1330Nearest Common Ancestors 1470 Closest Common Ancestors(LCA算法)
LCA思想:http://www.cnblogs.com/hujunzheng/p/3945885.html 在求解最近公共祖先为问题上,用到的是Tarjan的思想,从根结点开始形成一棵深搜树,非常好的处理技巧就是在回溯到结点u的时候,u的子树已经遍历,这…
干货 | 时间序列预测类问题下的建模方案探索实践
作者 | 陆春晖责编 | Carol出品 | AI科技大本营(ID:rgznai100)背景时间序列类问题是数据分析领域中一类常见的问题,人们有时需要通过观察某种现象一段时间的状态,来判断其未来一段时间的状态。而时间序列就是该种现象某一个统计指…
Redis安装与源码调试
linux版本:64位CentOS 6.5 Redis版本:redis-3.0.6 (更新到2016年1月22日) Redis官网:http://redis.io/ Redis常用命令:http://redis.io/commands 1.安装Redis # wget http://download.redis.io/releases/redis-3.2.6.tar.g…

system pause in C#
方法一: Console.Write("Press any key to continue . . . "); Console.ReadKey(true); 注:也可用ReadLine()或Read(),但是只能对回车进行响应,不能达到anykey的效果。 方法二: 1) 在源文件using处加入using…

C#设置当前程序通过IE代理服务器上网
注意:以下设置只在当前程序中有效,对IE浏览器无效,且关闭程序后,自动释放代码。 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Runtime.InteropServices;public static …

计算机科学精彩帖子收集
linux源码 LXR 源自“the Linux Cross Referencer”,中间的“X”形象地代表了“Cross”。与 Source Navigator 类似,它也是分析阅读源代码的好工具。不同的是,它将源代码借助浏览器展示出来,文件间的跳转过程成了我熟悉的点击超链…
挑战王者荣耀“绝悟” AI,我输了!
作者 | 马超责编 | 伍杏玲出品 | CSDN(ID:CSDNnews)腾讯 AI Lab 与王者荣耀联合研发的策略协作型AI,“绝悟”首次开放大规模开放:5月1日至4日,玩家从王者荣耀大厅入口,进入“挑战绝悟”测试&…

java 注解类说明
一、类中注解 SuppressWarnings ("serial"); 关键字 用途deprecation使用了不赞成使用的类或方法时的警告unchecked执行了未检查的转换时的警告,例如当使用集合时没有用泛型 (Generics) 来指定集合保存的类型。fallthrough当 Switch 程序块直接通往下一种…

《ArcGIS Runtime SDK for Android开发笔记》——(13)、图层扩展方式加载Google地图...
1、前言 http://mt2.google.cn/vt/lyrsm225000000&hlzh-CN&glcn&x420&y193&z9&sGalil 通过图层扩展类的方式加载Google地图的是我们通常获取Google地图的一种方式,根据这种方式我们可以通过拼接地图瓦片Url字符串获取瓦片数据,关…
调试JDK源码-一步一步看HashMap怎么Hash和扩容
调试JDK源码-一步一步看HashMap怎么Hash和扩容 调试JDK源码-ConcurrentHashMap实现原理 调试JDK源码-HashSet实现原理 调试JDK源码-调试JDK源码-Hashtable实现原理以及线程安全的原因 还是调试源码最好。 开发环境 JDK1.8NetBeans8.1 说明:调试HashMap的 publ…