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功能相关推荐

  1. internal java compiler error_java字节码注入AOP作业心得

    做的我心力憔悴,java太难了. 记录一下遇到的问题 导入别人的项目时,如果出现一大片error,首先检查是否导入JRE没有 如果是maven项目,记得加上maven Depedenies,右键项目- ...

  2. java修改字节码技术,Javassist修改class,ASM修改class

    背景: 项目使用的Logback 1.1.11版本的类ch.qos.logback.core.rolling.helper.RollingCalendar的periodBarriersCrossed方 ...

  3. OpenRasp Java运行时修改字节码技术

    Java运行时修改字节码技术 Java运行时动态修改字节码技术,常用的有javassist asm来实现.不过最近在分析openrasp-java这块时,程序使用的javassist来动态插桩关键类, ...

  4. jbe 可以用来修改Java class的字节码,配合jd-gui 使用

    jbe  可以用来修改Java class的字节码,配合jd-gui 使用 转载于:https://www.cnblogs.com/rirtue/p/9626490.html

  5. java 字节码增强原理_深入浅出Java探针技术1--基于java agent的字节码增强案例

    Java agent又叫做Java 探针,本文将从以下四个问题出发来深入浅出了解下Java agent 一.什么是java agent? Java agent是在JDK1.5引入的,是一种可以动态修改 ...

  6. java探针 字节码增强_深入浅出Java探针技术1--基于java agent的字节码增强案例

    Java agent又叫做Java 探针,本文将从以下四个问题出发来深入浅出了解下Java agent 一.什么是java agent? Java agent是在JDK1.5引入的,是一种可以动态修改 ...

  7. JVM笔记:Java虚拟机的字节码指令详解

    1.字节码 Java能发展到现在,其"一次编译,多处运行"的功能功不可没,这里最主要的功劳就是JVM和字节码了,在不同平台和操作系统上根据JVM规范的定制JVM可以运行相同字节码( ...

  8. Android 进阶之路:ASM 修改字节码,这样学就对了!

    本文已授权个人公众号「鸿洋」原创发布. 恢复双休了,准备捡起来写博客这件事,会尝试写好每一篇博客,准备写一个「进阶之路」的系列,希望对你有用. 没错,看了很多 ASM 入门的文章,都感觉文章写的很轻松 ...

  9. Java 指令与字节码

    Java 指令与字节码 查看class文件 编写简单java代码 编译代码 查看class文件 Java字节码总的结构表 常量池 常量池容量计数器 字面量和符号引用 全限定名 简单名称 描述符 常量类 ...

最新文章

  1. 《Linux From Scratch》第二部分:准备构建 第三章:软件包与补丁- 3.1. 简介
  2. 对讲机的那点事:带你玩转LD800数字车载台读、写频操作:一
  3. 用U盘破除XP管理员密码
  4. 2021年Q2:全球超大规模数据中心数量增至659个
  5. 用matlab定义2020年元旦是星期三,如何用matlab实现某年某月某日是星期几的问题,...
  6. asp.net中实现文件批量上传
  7. 2018年工业机器人销量排位_长安-2018年11月汽车销量 细分销量
  8. Android HAL 层,三个重要的结构体的源码~
  9. to_number用法示例_Number()函数以及JavaScript中的示例
  10. 漳州职业技术学院计算机学费多少钱,漳州职业技术学院单招2021年学费多少
  11. 大班音乐机器人反思_幼儿园大班音乐律动教案《伦敦桥》含反思
  12. input reset 重置时间
  13. spring学习-xml属性注入-数组--list--map--set类型
  14. HDFVIEW3.1.2下载
  15. 数值计算实验1 Matlab基础实验
  16. React项目中使用Dplayer播放FLV格式视频教程(不支持ios)
  17. 如何在Python中异步操作数据库?
  18. 2021毓英中学高考成绩查询,泉州知名中学2020高考成绩喜报龙虎榜
  19. 反激式开关电源输出电压的PID控制之MATLAB仿真
  20. 分组加密中的四种模式(ECB、CBC、CFB、OFB)

热门文章

  1. easyui弹出窗关闭前调用确认窗口,先关闭页面后调用弹出窗口
  2. RT-thread内核之对象管理系统
  3. Android系统Recovery工作原理之使用update.zip升级过程分析(四)
  4. 设备的开发【WP7学习札记之五】
  5. ES6学习(六)—函数的扩展
  6. 计算机网络—路由器(Cisco Packet Tracer)常用的命令总结
  7. 修改oracle超空间大小,Oracle修改表空间大小详解
  8. 什么是暗物质?有没有理科大神解答一下啊?
  9. 48周岁交的社保,加医疗合计每月1200,想问问退休能开多少?
  10. 产品泛滥的时代,如何让你的产品脱颖而出?