字节码插桩

我们知道JVM是不能直接执行.java 代码,也不能直接执行.class文件,它只能执行.class 文件中存储的指令码。这就是为什么class需要通过classLoader 装载以后才能运行。基于此机制可否在ClassLoader装载之前拦截修改class当中的内容(jvm 指令码)从而让程序中包含我们的埋点逻辑呢?答案是肯定的,但需要用到两个技术 javaagent与javassist 。前者用于拦截ClassLoad装载,后者用于操作修改class文件。

javaagent

javaagent介绍

javaagent 是java1.5之后引入的特性,其主要作用是在class 被加载之前对其拦截,以插入我们的监听字节码

javaagent jar包

javaagent 最后展现形式是一个Jar包,有以下特性:

1.必须 META-INF/MANIFEST.MF中指定Premain-Class 设定启agent启动类。

2.在启类需写明启动方法 public static void main(String arg,)

3.不可直接运行,只能通过 jvm 参数-javaagent:xxx.jar 附着于其它jvm 进程运行。

javaagent使用

1、编写agent方法

public classMyAgent {public static void premain(String args, Instrumentation instrumentation) throwsException {

System.out.println("Hello javaagent permain:"+args);

}

}

2、添加premain-class参数

org.apache.maven.plugins

maven-jar-plugin

2.2

${project.name}

${project.version}

com.javaagent.MyAgent

true

true

true

3、构建打包

4、在任一JAVA应用中 添加jvm 参数并启动 -javaagent:xxx.jarjavaagent META-INF/MANIFEST.MF

参数说明:

Premain-Class:必填,agent启动

classCan-Redefine-Classes:默认为false ,是否允许重新定义

classCan-Retransform-Classes:默认为false,是否允许重置Class,重置后相当于class 从classLoade中清除,下次有需要的时候会重新装载,也会重新走Transformer 流程。

Boot-Class-Path:agent 所依赖的jar 路径,多个用空格分割

创建一个测试类MyAgentTest并运行查看结果

public classMyAgentTest {public static voidmain(String[] args) {

System.out.println("main");

}

}//运行结果:main

添加jvm参数

参数内容:-javaagent:/Users/jinyunlong/IdeaProjects/test-agent/target/test-agent-1.0-SNAPSHOT.jar=123

再次运行测试类MyAgentTest并查看结果

javassist

javassist介绍

javassist是一个开源的分析、编辑和创建Java字节码的类库。其主要的优点,在于简单,而且快速。直接使用java编码的形式,而不需要了解虚拟机指令,就能动态改变类的结构,或者动态生成(注:也可以使用ASM实现,但需要会操作字节码指令,学习使用成本高)

javassist使用

使用javassist需要引入javasssist的jar包,添加内容如下:

org.javassist

javassist

3.18.1-GA

org.apache.maven.plugins

maven-jar-plugin

2.2

${project.name}

${project.version}

com.javaagent.MyAgent

true

true

javassist-3.18.1-GA.jar

true

演示插入打印当前时间

创建类MyServer

public classMyServer {publicInteger sayHello(String name,String message){

System.out.println("hello");return 0;

}

}

myAgent类

创建测试类并调用MyServer中的sayHello方法

演示计算方法调用时间

类MyAgent

public classMyAgent {public static void premain(String args, Instrumentation instrumentation) throwsException {

instrumentation.addTransformer(newClassFileTransformer() {public byte[] transform(ClassLoader loader, String className, Class>classBeingRedefined, ProtectionDomain protectionDomain,byte[] classfileBuffer) throwsIllegalClassFormatException {if(!"com/javaagent/MyServer".equals(className)){return null;

}try{returnbuildMonitorClass();

}catch(Exception e) {

e.printStackTrace();

}return null;

}

},true);

}private static byte[] buildMonitorClass() throwsException{/*** 1、拷贝一个新的方法

* 2、修改原方法名

* 3、加入监听代码*/ClassPool pool= newClassPool();

pool.appendSystemPath();

CtClass ctClass= pool.get("com.javaagent.MyServer");

CtMethod ctMethod= ctClass.getDeclaredMethod("sayHello");

CtMethod copyMethod= CtNewMethod.copy(ctMethod,ctClass,newClassMap());

ctMethod.setName("sayHello$agent");

copyMethod.setBody("{\n" +

" long begin = System.nanoTime();\n" +

" try {\n" +

" return sayHello$agent($1,$2);\n" +

" } finally {\n" +

" System.out.println(System.nanoTime() - begin);}\n" +

" }");

ctClass.addMethod(copyMethod);returnctClass.toBytecode();

}

}

修改类MyServer

public classMyServer {publicInteger sayHello(String name,String message){

System.out.println("hello name:"+name+",message:"+message);return 0;

}

}

修改测试类并运行

public classMyAgentTest {public static voidmain(String[] args) {

MyServer myServer= newMyServer();

myServer.sayHello("paul","1234");

}

}//运行结果:

hello name:paul,message:1234

186537

javassist特殊语法

插桩java_字节码插桩技术相关推荐

  1. 字节码插桩(javassist)之插入代码块|IOC框架(Hilt)之对象注入~研究

    Hilt对象注入 | javassist插桩 研究 Hilt对象注入 javassist字节码插桩 创建buildSrc的module 重写Transform 熟悉TransformInvocatio ...

  2. 字节码插桩框架ASM(一)

    本文大纲: ams是做什么的 asm使用 1.ASM是做什么的? 简单来说,asm是用来进行字节码插桩的.什么是字节码插桩? 字节码插桩就是修改节码文件(.class). 如同 gson框架是用来做操 ...

  3. 调研字节码插桩技术,用于系统监控设计和实现

    作者:小傅哥 博客:https://bugstack.cn ❝ 沉淀.分享.成长,让自己和他人都能有所收获!???? ❞ 目录 一.来自深夜的电话! 二.准备工作 三.使用 AOP 做个切面监控 1. ...

  4. 【字节码插桩】AOP 技术 ( “字节码插桩“ 技术简介 | AspectJ 插桩工具 | ASM 插桩工具 )

    文章目录 一." 字节码插桩 " 技术简介 二.AspectJ 插桩工具 三.ASM 插桩工具 一." 字节码插桩 " 技术简介 性能优化 , 插件化 , 热修 ...

  5. 【字节码插桩】Android 打包流程 | Android 中的字节码操作方式 | AOP 面向切面编程 | APT 编译时技术

    文章目录 一.Android 中的 Java 源码打包流程 1.Java 源码打包流程 2.字符串常量池 二.Android 中的字节码操作方式 一.Android 中的 Java 源码打包流程 Ja ...

  6. 【网上的都不靠谱?还是得改源码】用Javasisst的字节码插桩技术,彻底解决Gson转Map时,Int变成double问题...

    一.探究原由 首先申明一下,我们要解决的问题有两个: Json串转Map时,int变double问题 Json串转对象时,对象属性中的Map,int变double问题 然后,我们来了解一下,Gson实 ...

  7. Android AOP之字节码插桩

    背景   本篇文章基于<网易乐得无埋点数据收集SDK>总结而成,关于网易乐得无埋点数据采集SDK的功能介绍以及技术总结后续会有文章进行阐述,本篇单讲SDK中用到的Android端AOP的实 ...

  8. aop 获取方法入参出参_ASM字节码编程 | JavaAgent+ASM字节码插桩采集方法名称及入参和出参结果并记录方法耗时...

    作者:小傅哥 博客:bugstack.cn ❝ 沉淀.分享.成长,让自己和他人都能有所收获! ❞ 一.前言 在我们实际的业务开发到上线的过程中,中间都会经过测试.那么怎么来保证测试质量呢?比如:提交了 ...

  9. 看完这一篇,你也可以自如地掌握字节码插桩

    /   今日科技快讯   / 近日,一些国家的黑客频繁对俄罗斯发动网络攻击,以阻止它们正常运行.未来几天,俄罗斯可能与全球互联网断开.针对网络威胁,俄罗斯政府准备启动自己的"大局域网&quo ...

  10. Android字节码插桩

    什么是字节码插桩 字节码插桩就是在构建的过程中,通过修改已经编译完成的字节码文件,也就是class文件,来实现功能的添加. 简单来讲,我们要实现无埋点对客户端的全量统计.这里的统计概括的范围比较广泛, ...

最新文章

  1. java process started_Java HistoricProcessInstanceQuery.startedBy方法代碼示例
  2. halcon的算子清点: Chapter 5 滤波
  3. 树结构之树和二叉树的概念以及如何用面向对象思想进行结构定义01
  4. bzoj5039:[Jsoi2014]序列维护
  5. matlab画图模糊,[转载]matlab中模糊工具箱的使用
  6. engagement center里如何获得Access Token
  7. spring mvc拦截器_Spring MVC拦截器示例
  8. 走进Windows Server 2008服务器核心(Serve Core)
  9. TensorFlow11CNN和全卷积神经网络
  10. NDK配置文件Android.mk简介
  11. 数据库习题(填空题一)
  12. 软件测试简历项目经验怎么写,没有项目经验?
  13. SecureCRT 7.3.4 安装图解----破解图解
  14. 锐捷交换机VRRP配置
  15. 幻梦一场:Vulcan Project
  16. 【JAVA长虹键法】第 十二式 外观模式(23种设计模式)
  17. Android10 SystemUI状态栏网络图标流程分析
  18. 全面理解-Flutter(万字长文,【性能优化实战】
  19. 计算物理学(数值分析)上机实验答案5、常微分方程初值问题的数值解法
  20. pytorch中的MSELoss函数

热门文章

  1. win10计算机的用户名和密码在哪里查,Win10查看别人在自己电脑上输入过的账号密码...
  2. 牛顿插值法的Python程序
  3. 奥普泰安防监控智能配电箱——为安防行业添新助力
  4. 探索实践之软件构建(一)
  5. C++银行管理系统源代码
  6. PS制作一寸带白框的证件照
  7. Android UI:使用矢量图,抛弃PNG
  8. vnc远程访问linux服务器,如何通过 VNC 远程访问 Linux 虚拟机
  9. 被裁员工公开呛声IBM人工智能,有双好鞋却不知怎么走路
  10. 蔡勒公式整理——给日期计算星期几