当前位置: 首页 > 编程日记 > 正文

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 使用指南(三)

相关文章:

怎样保持良好的心态

有一位朋友有一次气冲冲的跟我说&#xff1a;“气死我了&#xff01;我刚刚发现我一位员工出了错&#xff0c;令产品出现了质量的问题&#xff0c;我修理了他一顿。。。 我问&#xff1a;”你认为你的生产流程里面可能一点错误都没有吗&#xff1f;“ 他说&#xff1a;”应该不…

web编程速度大比拼(nodejs go python)(非专业对比)

C10K问题的解决&#xff0c;涌现出一大批新框架&#xff0c;或者新语言&#xff0c;那么问题来了:到底谁最快呢&#xff1f;非专业程序猿来个非专业对比。 比较程序&#xff1a;输出Hello World&#xff01; 测试程序&#xff1a;siege –c 100 –r 100 –b 例子包括&#xff1…

linux邮件服务

邮件服务要求:l 能够构建完整的邮件系统 能够正确设置DNS邮件服务器记录 l 能够配置sendmail服务器 设置客户端软件使用邮件服务器 准备工作&#xff1a; l 主机名&#xff1a;srv.benet.com /etc/sysconfig/network <永久的> l 域名 正向区域 bt.com完成NDS的…

MaskFlownet:基于可学习遮挡掩模的非对称特征匹配丨CVPR 2020

来源 | 微软研究院AI头条&#xff08;ID: MSRAsia&#xff09;编者按&#xff1a;在光流预测任务中&#xff0c;形变带来的歧义与无效信息会干扰特征匹配的结果。在这篇 CVPR 2020 Oral 论文中&#xff0c;微软亚洲研究院提出了一种可学习遮挡掩模的非对称特征匹配模块 &#x…

GDB调试--以汇编语言为例

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

汇编语言系统调用过程

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

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安全诊断大师”

如同一些出生免疫力就有缺陷的人一样&#xff0c;AI也存在免疫力缺陷。基于从源头打造安全免疫力的新一代安全架构理念&#xff0c;最近&#xff0c;阿里安全研究发布了一项核心技术“AI安全诊断大师”&#xff0c;可对AI模型全面体检&#xff0c;“看诊开方”&#xff0c;让AI…

Spring学习总结(7)——applicationContext.xml 配置文详解

web.xml中classpath:和classpath*: 有什么区别? classpath&#xff1a;只会到你的class路径中查找找文件; classpath*&#xff1a;不仅包含class路径&#xff0c;还包括jar文件中(class路径)进行查找. 存放位置&#xff1a; 1&#xff1a;src下面 需要在web.xml中定义如下&…

GDB查看栈信息

栈&#xff1a;是程序存放数据内存区域之一&#xff0c;特点是LIFO&#xff08;后进先出&#xff09;。 PUSH&#xff1a;入栈 POP&#xff1a;出战 使用场景&#xff1a; 1.保存动态分配的自动变量使用栈 2.函数调用时&#xff0c;用栈传递函数参数&#xff0c;半寸返回地址…

数据库学习之路

今天迎来入冬的第二场雪&#xff0c;闲来无事就整理了下总结下工作以来所有数据库方面的书籍和资料&#xff0c;发现了不少&#xff0c;很多已经读过或者正在读的书籍&#xff0c;oracle真的很强大&#xff0c;直到现在发现才入门的水平&#xff0c;当然很多书读一遍是不行的&a…

为什么铺天盖地都是Python的广告?

最近&#xff0c;知乎关于Python有一个热议问题&#xff1a; 甚至在抖音上&#xff0c;笔者有一次还看到Python占领了热搜&#xff01;应该有很多不懂技术的吃瓜群众也被Python的热度炒懵了……但是&#xff0c;Python真的值得学吗&#xff1f;真的值得花这么多钱去学吗&#x…

python3正则表达式符号和用法

转载于:https://www.cnblogs.com/wumac/p/5441322.html

从寄存器看I386和x64位中函数调用中参数传递

x86_64基本使用寄存器存储函数参数&#xff0c;寄存器不够才入栈&#xff1b; 而i386将所有参数保存在栈上&#xff0c;通过gcc的扩展功能__attribute__((regparm()))即可实现部分参数的寄存器传递。 调试语法&#xff1a; --《深入理解计算机系统(原书第2版)》 代码 #incl…

转:去掉Flex4生成的SWF加载时的进度条

方法一&#xff1a; <?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年演化史

作者 | 挽晴来源 | 阿里巴巴中间件&#xff08;ID&#xff1a;Aliware_2018&#xff09;个人简介:2014年12月加入饿了么&#xff0c;当时参与后台系统的研发(WalisJavis>Walle)&#xff0c;主要面向客服和BD。2015年5月开始接触订单系统的研发&#xff0c;7月负责订单研发组…

Python迁移MySQL数据到MongoDB脚本

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

使用valgrind分析C程序调用线路图

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

纯CSS实现蓝色圆角下拉菜单

代码简介&#xff1a; 这个菜单没有使用任何的图片&#xff0c;完全是用CSS实现的&#xff0c;包括圆角效果也同样是&#xff0c;而且还考虑了多浏览器的兼容性&#xff0c;可以说非常不错&#xff0c;既兼容性好&#xff0c;又外观漂亮&#xff0c;下拉导航菜单目前比较流行&a…

生产型机器学习已经没那么困难了?

作者 | Caleb Kaiser译者 | 香槟超新星出品 | CSDN&#xff08;ID:CSDNnews&#xff09;封面图源自视觉中国在软件工程的诸多领域内&#xff0c;生产用例是相当标准化的。以Web开发为例&#xff0c;要在Web应用中实现身份认证&#xff0c;你不会去创造一个数据库&#xff0c;自…

poj1330Nearest Common Ancestors 1470 Closest Common Ancestors(LCA算法)

LCA思想&#xff1a;http://www.cnblogs.com/hujunzheng/p/3945885.html 在求解最近公共祖先为问题上&#xff0c;用到的是Tarjan的思想&#xff0c;从根结点开始形成一棵深搜树&#xff0c;非常好的处理技巧就是在回溯到结点u的时候&#xff0c;u的子树已经遍历&#xff0c;这…

干货 | 时间序列预测类问题下的建模方案探索实践

作者 | 陆春晖责编 | Carol出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09;背景时间序列类问题是数据分析领域中一类常见的问题&#xff0c;人们有时需要通过观察某种现象一段时间的状态&#xff0c;来判断其未来一段时间的状态。而时间序列就是该种现象某一个统计指…

Redis安装与源码调试

linux版本&#xff1a;64位CentOS 6.5 Redis版本&#xff1a;redis-3.0.6 (更新到2016年1月22日) Redis官网&#xff1a;http://redis.io/ Redis常用命令&#xff1a;http://redis.io/commands 1.安装Redis # wget http://download.redis.io/releases/redis-3.2.6.tar.g…

system pause in C#

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

C#设置当前程序通过IE代理服务器上网

注意&#xff1a;以下设置只在当前程序中有效&#xff0c;对IE浏览器无效&#xff0c;且关闭程序后&#xff0c;自动释放代码。 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Runtime.InteropServices;public static …

计算机科学精彩帖子收集

linux源码 LXR 源自“the Linux Cross Referencer”&#xff0c;中间的“X”形象地代表了“Cross”。与 Source Navigator 类似&#xff0c;它也是分析阅读源代码的好工具。不同的是&#xff0c;它将源代码借助浏览器展示出来&#xff0c;文件间的跳转过程成了我熟悉的点击超链…

挑战王者荣耀“绝悟” AI,我输了!

作者 | 马超责编 | 伍杏玲出品 | CSDN&#xff08;ID&#xff1a;CSDNnews&#xff09;腾讯 AI Lab 与王者荣耀联合研发的策略协作型AI&#xff0c;“绝悟”首次开放大规模开放&#xff1a;5月1日至4日&#xff0c;玩家从王者荣耀大厅入口&#xff0c;进入“挑战绝悟”测试&…

java 注解类说明

一、类中注解 SuppressWarnings ("serial"); 关键字 用途deprecation使用了不赞成使用的类或方法时的警告unchecked执行了未检查的转换时的警告&#xff0c;例如当使用集合时没有用泛型 (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地图的一种方式&#xff0c;根据这种方式我们可以通过拼接地图瓦片Url字符串获取瓦片数据&#xff0c;关…

调试JDK源码-一步一步看HashMap怎么Hash和扩容

调试JDK源码-一步一步看HashMap怎么Hash和扩容 调试JDK源码-ConcurrentHashMap实现原理 调试JDK源码-HashSet实现原理 调试JDK源码-调试JDK源码-Hashtable实现原理以及线程安全的原因 还是调试源码最好。 开发环境 JDK1.8NetBeans8.1 说明&#xff1a;调试HashMap的 publ…