java Instrument修改字节码实现aop功能
Agent工程2个类:
public class MyAgent {/*** 该方法在main方法之前运行,与main方法运行在同一个JVM中* 并被同一个System ClassLoader装载* 被统一的安全策略(security policy)和上下文(context)管理*/public static void premain(String agentOps, Instrumentation inst) {System.out.println("=========premain方法执行========");System.out.println(agentOps);// 添加Transformerinst.addTransformer(new MyTransformer());}/*** 如果不存在 premain(String agentOps, Instrumentation inst) * 则会执行 premain(String agentOps)*/public static void premain(String agentOps) {System.out.println("=========premain方法执行2========");System.out.println(agentOps);}}
public class MyTransformer implements ClassFileTransformer {final static String prefix = "\nlong startTime = System.currentTimeMillis();\n";final static String postfix = "\nlong endTime = System.currentTimeMillis();\n";// 被处理的方法列表final static Map<String, List<String>> methodMap = new HashMap<String, List<String>>();public MyTransformer() {add("com.hwtest.demo.MyProgram.sayHello");add("com.hwtest.demo.MyProgram.sayHello2");}private void add(String methodString) {String className = methodString.substring(0, methodString.lastIndexOf("."));String methodName = methodString.substring(methodString.lastIndexOf(".") + 1);List<String> list = methodMap.get(className);if (list == null) {list = new ArrayList<String>();methodMap.put(className, list);}list.add(methodName);}@Overridepublic byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined,ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {className = className.replace("/", ".");if (methodMap.containsKey(className)) {// 判断加载的class的包路径是不是需要监控的类CtClass ctclass = null;try {ctclass = ClassPool.getDefault().get(className);// 使用全称,用于取得字节码类<使用javassist>for (String methodName : methodMap.get(className)) {String outputStr = "\nSystem.out.println(\"this method " + methodName+ " cost:\" +(endTime - startTime) +\"ms.\");";CtMethod ctmethod = ctclass.getDeclaredMethod(methodName);// 得到这方法实例String newMethodName = methodName + "$old";// 新定义一个方法叫做比如sayHello$oldctmethod.setName(newMethodName);// 将原来的方法名字修改// 创建新的方法,复制原来的方法,名字为原来的名字CtMethod newMethod = CtNewMethod.copy(ctmethod, methodName, ctclass, null);// 构建新的方法体StringBuilder bodyStr = new StringBuilder();bodyStr.append("{");bodyStr.append(prefix);bodyStr.append(newMethodName + "($$);\n");// 调用原有代码,类似于method();($$)表示所有的参数 bodyStr.append(postfix);bodyStr.append(outputStr);bodyStr.append("}");newMethod.setBody(bodyStr.toString());// 替换新方法ctclass.addMethod(newMethod);// 增加新方法 }return ctclass.toBytecode();} catch (Exception e) {System.out.println(e.getMessage());e.printStackTrace();}}return null;} }
原始项目:
public class MyProgram {public static void main(String[] args) {sayHello();sayHello2("hello world222222222");}public static void sayHello() {try {Thread.sleep(2000);System.out.println("hello world!!");} catch (InterruptedException e) {e.printStackTrace();}}public static void sayHello2(String hello) {try {Thread.sleep(1000);System.out.println(hello);} catch (InterruptedException e) {e.printStackTrace();}} }
agent项目打jar包是配置为:
Manifest-Version: 1.0 Premain-Class: com.hwtest.MyAgent Can-Redefine-Classes: true Boot-Class-Path: javassist.jar
cmd执行命令
java -javaagent:MyAgent.jar -jar MyProgram.jar=========premain方法执行======== null hello world!! this method sayHello cost:2000ms. hello world222222222 this method sayHello2 cost:1000ms.
附:agent jar中manifest的属性
- Premain-Class: 当在VM启动时,在命令行中指定代理jar时,必须在manifest中设置Premain-Class属性,值为代理类全类名,并且该代理类必须提供premain方法。否则JVM会异常终止。
- Agent-Class: 当在VM启动之后,动态添加代理jar包时,代理jar包中manifest必须设置Agent-Class属性,值为代理类全类名,并且该代理类必须提供agentmain方法,否则无法启动该代理。
- Boot-Class-Path: Bootstrap class loader加载类时的搜索路径,可选。
- Can-Redefine-Classes: true/false;标示代理类是否能够重定义类。可选。
- Can-Retransform-Classes: true/false;标示代理类是否能够转换类定义。可选。
- Can-Set-Native-Prefix::true/false;标示代理类是否需要本地方法前缀,可选。
当一个代理jar包中的manifest文件中既有Premain-Class又有Agent-Class时,如果以命令行方式在VM启动前指定代理jar,则使用Premain-Class;反之如果在VM启动后,动态添加代理jar,则使用Agent-Class
地址记录:
(1)利用ClassFileTransformer实现aop:http://xj84.iteye.com/blog/1221105
(2)Java通过修改类的字节码实现aop功能:http://www.360doc.com/content/07/0518/11/25392_506401.shtml
(3)java.lang.instrument动态修改替换类代码:http://zctya.blog.163.com/blog/static/1209178201131944127774/
转载于:https://www.cnblogs.com/nnavvi/p/7340910.html
java Instrument修改字节码实现aop功能相关推荐
- internal java compiler error_java字节码注入AOP作业心得
做的我心力憔悴,java太难了. 记录一下遇到的问题 导入别人的项目时,如果出现一大片error,首先检查是否导入JRE没有 如果是maven项目,记得加上maven Depedenies,右键项目- ...
- java修改字节码技术,Javassist修改class,ASM修改class
背景: 项目使用的Logback 1.1.11版本的类ch.qos.logback.core.rolling.helper.RollingCalendar的periodBarriersCrossed方 ...
- OpenRasp Java运行时修改字节码技术
Java运行时修改字节码技术 Java运行时动态修改字节码技术,常用的有javassist asm来实现.不过最近在分析openrasp-java这块时,程序使用的javassist来动态插桩关键类, ...
- jbe 可以用来修改Java class的字节码,配合jd-gui 使用
jbe 可以用来修改Java class的字节码,配合jd-gui 使用 转载于:https://www.cnblogs.com/rirtue/p/9626490.html
- java 字节码增强原理_深入浅出Java探针技术1--基于java agent的字节码增强案例
Java agent又叫做Java 探针,本文将从以下四个问题出发来深入浅出了解下Java agent 一.什么是java agent? Java agent是在JDK1.5引入的,是一种可以动态修改 ...
- java探针 字节码增强_深入浅出Java探针技术1--基于java agent的字节码增强案例
Java agent又叫做Java 探针,本文将从以下四个问题出发来深入浅出了解下Java agent 一.什么是java agent? Java agent是在JDK1.5引入的,是一种可以动态修改 ...
- JVM笔记:Java虚拟机的字节码指令详解
1.字节码 Java能发展到现在,其"一次编译,多处运行"的功能功不可没,这里最主要的功劳就是JVM和字节码了,在不同平台和操作系统上根据JVM规范的定制JVM可以运行相同字节码( ...
- Android 进阶之路:ASM 修改字节码,这样学就对了!
本文已授权个人公众号「鸿洋」原创发布. 恢复双休了,准备捡起来写博客这件事,会尝试写好每一篇博客,准备写一个「进阶之路」的系列,希望对你有用. 没错,看了很多 ASM 入门的文章,都感觉文章写的很轻松 ...
- Java 指令与字节码
Java 指令与字节码 查看class文件 编写简单java代码 编译代码 查看class文件 Java字节码总的结构表 常量池 常量池容量计数器 字面量和符号引用 全限定名 简单名称 描述符 常量类 ...
最新文章
- 《Linux From Scratch》第二部分:准备构建 第三章:软件包与补丁- 3.1. 简介
- 对讲机的那点事:带你玩转LD800数字车载台读、写频操作:一
- 用U盘破除XP管理员密码
- 2021年Q2:全球超大规模数据中心数量增至659个
- 用matlab定义2020年元旦是星期三,如何用matlab实现某年某月某日是星期几的问题,...
- asp.net中实现文件批量上传
- 2018年工业机器人销量排位_长安-2018年11月汽车销量 细分销量
- Android HAL 层,三个重要的结构体的源码~
- to_number用法示例_Number()函数以及JavaScript中的示例
- 漳州职业技术学院计算机学费多少钱,漳州职业技术学院单招2021年学费多少
- 大班音乐机器人反思_幼儿园大班音乐律动教案《伦敦桥》含反思
- input reset 重置时间
- spring学习-xml属性注入-数组--list--map--set类型
- HDFVIEW3.1.2下载
- 数值计算实验1 Matlab基础实验
- React项目中使用Dplayer播放FLV格式视频教程(不支持ios)
- 如何在Python中异步操作数据库?
- 2021毓英中学高考成绩查询,泉州知名中学2020高考成绩喜报龙虎榜
- 反激式开关电源输出电压的PID控制之MATLAB仿真
- 分组加密中的四种模式(ECB、CBC、CFB、OFB)