背景:美团的技术沙龙分享的文章都还是很不错的,通俗易懂,开阔视野,后面又机会要好好实践一番。

Java动态追踪技术探究

楔子

jsp的修改 重新加载不需要重启servlet。如何在不重启jvm的情况下,修改一个对象的行为呢?

Java的对象行为(方法、函数)是存储在方法区的。

“倒着推,手写没问题,编译没问题,至于加载……有没有办法加载一个已经加载过的类呢?如果有的话,我们就能修改字节码中目标方法所在的区域,然后重新加载这个类,这样方法区中的对象行为(方法)就被改变了,而且不改变对象的属性,也不影响已经存在对象的状态,那么就可以搞定这个问题了。可是,这岂不是违背了JVM的类加载原理?毕竟我们不想改变ClassLoader。”

“少年,可以去看看java.lang.instrument.Instrumentation。”

java.lang.instrument.Instrumentation

看完文档之后,我们发现这么两个接口:redefineClasses和retransformClasses。一个是重新定义class,一个是修改class。

都是替换已经存在的class文件,redefineClasses是自己提供字节码文件替换掉已存在的class文件,retransformClasses是在已存在的字节码文件上修改后再替换之。

当然,运行时直接替换类很不安全。比如新的class文件引用了一个不存在的类,或者把某个类的一个field给删除了等等,这些情况都会引发异常。所以如文档中所言,instrument存在诸多的限制:

直接操作字节码

Java是软件开发人员能读懂的语言,class字节码是JVM能读懂的语言,class字节码最终会被JVM解释成机器能读懂的语言。无论哪种语言,都是人创造的。所以,理论上(实际上也确实如此)人能读懂上述任何一种语言,既然能读懂,自然能修改。只要我们愿意,我们完全可以跳过Java编译器,直接写字节码文件,只不过这并不符合时代的发展罢了,毕竟高级语言设计之始就是为我们人类所服务,其开发效率也比机器语言高很多。

对于人类来说,字节码文件的可读性远远没有Java代码高。尽管如此,还是有一些杰出的程序员们创造出了可以用来直接编辑字节码的框架,提供接口可以让我们方便地操作字节码文件,进行注入修改类的方法,动态创造一个新的类等等操作。其中最著名的框架应该就是ASM了,cglib、Spring等框架中对于字节码的操作就建立在ASM之上。

我们都知道,Spring的AOP是基于动态代理实现的,Spring会在运行时动态创建代理类,代理类中引用被代理类,在被代理的方法执行前后进行一些神秘的操作。那么,Spring是怎么在运行时创建代理类的呢?动态代理的美妙之处,就在于我们不必手动为每个需要被代理的类写代理类代码,Spring在运行时会根据需要动态地创造出一个类,这里创造的过程并非通过字符串写Java文件,然后编译成class文件,然后加载。Spring会直接“创造”一个class文件,然后加载,创造class文件的工具,就是ASM了。

到这里,我们知道了用ASM框架直接操作class文件,在类中加一段打印日志的代码,然后调用retransformClasses就可以了

BTrace

A safe, dynamic tracing tool for the Java platform.

BTrace是基于Java语言的一个安全的、可提供动态追踪服务的工具。BTrace基于ASM、Java Attach Api、Instruments开发,为用户提供了很多注解。依靠这些注解,我们可以编写BTrace脚本(简单的Java代码)达到我们想要的效果,而不必深陷于ASM对字节码的操作中不可自拔。

PS:精华

Trace主要有下面几个模块:

  1. BTrace脚本:利用BTrace定义的注解,我们可以很方便地根据需要进行脚本的开发。
  2. Compiler:将BTrace脚本编译成BTrace class文件。
  3. Client:将class文件发送到Agent。
  4. Agent:基于Java的Attach Api,Agent可以动态附着到一个运行的JVM上,然后开启一个BTrace Server,接收client发过来的BTrace脚本;解析脚本,然后根据脚本中的规则找到要修改的类;修改字节码后,调用Java Instrument的reTransform接口,完成对对象行为的修改并使之生效。

整个BTrace的架构大致如下:

BTrace工作流程

BTrace最终借Instruments实现class的替换。如上文所说,出于安全考虑,Instruments在使用上存在诸多的限制,BTrace也不例外。BTrace对JVM来说是“只读的”,因此BTrace脚本的限制如下:

  1. 不允许创建对象
  2. 不允许创建数组
  3. 不允许抛异常
  4. 不允许catch异常
  5. 不允许随意调用其他对象或者类的方法,只允许调用com.sun.btrace.BTraceUtils中提供的静态方法(一些数据处理和信息输出工具)
  6. 不允许改变类的属性
  7. 不允许有成员变量和方法,只允许存在static public void方法
  8. 不允许有内部类、嵌套类
  9. 不允许有同步方法和同步块
  10. 不允许有循环
  11. 不允许随意继承其他类(当然,java.lang.Object除外)
  12. 不允许实现接口
  13. 不允许使用assert
  14. 不允许使用Class对象

如此多的限制,其实可以理解。BTrace要做的是,虽然修改了字节码,但是除了输出需要的信息外,对整个程序的正常运行并没有影响。

Arthas

BTrace脚本在使用上有一定的学习成本,如果能把一些常用的功能封装起来,对外直接提供简单的命令即可操作的话,那就再好不过了。阿里的工程师们早已想到这一点,就在去年(2018年9月份),阿里巴巴开源了自己的Java诊断工具——Arthas。Arthas提供简单的命令行操作,功能强大。究其背后的技术原理,和本文中提到的大致无二。Arthas的文档很全面,想详细了解的话可以戳这里

本文旨在说明Java动态追踪技术的来龙去脉,掌握技术背后的原理之后,只要愿意,各位读者也可以开发出自己的“冰封王座”出来。

(转)Java动态追踪技术探究的更多相关文章

  1. Java动态追踪技术探究(动态修改)

    Java动态追踪技术探究 Java探针-Java Agent技术-阿里面试题 秒懂Java动态编程(Javassist研究) 可以用于在类加载的时候,修改字节码. Java agent(Java探针) ...

  2. Java动态追踪技术探究

    引子 在遥远的希艾斯星球爪哇国塞沃城中,两名年轻的程序员正在为一件事情苦恼,程序出问题了,一时看不出问题出在哪里,于是有了以下对话: “Debug一下吧.” “线上机器,没开Debug端口.” “看日 ...

  3. 【基本功】Java动态追踪技术探究 不重启JVM,替换掉已经加载的类?不重启JVM,获知运行时对象的属性

    https://mp.weixin.qq.com/s/_hSaI5yMvPTWxvFgl-UItA 小结: 1.根据Java的类加载机制,在同一个ClassLoader中,类是不允许重复的: 2.单例 ...

  4. Java 动态调试技术原理及实践 【基本功】Java动态追踪技术探究

    https://mp.weixin.qq.com/s/ZlNcvwJ_swspifWTLHA92Q https://mp.weixin.qq.com/s/_hSaI5yMvPTWxvFgl-UItA

  5. 动态追踪技术(中) - Dtrace、SystemTap、火焰图

    http://openresty.org/cn/presentations.html http://weibo.com/agentzh?is_all=1 http://openresty.org/po ...

  6. Java数据库连接技术——JDBC

    大家好,今天我们学习了Java如何连接数据库.之前学过.net语言的数据库操作,感觉就是一通百通,大同小异. JDBC是Java数据库连接技术的简称,提供连接各种常用数据库的能力. JDBC API ...

  7. java 深入技术八(内省)

    1. javabean的软件设计思想 2.内省:封装了java反射,提供直接操作属性的Setter和getter方法的方法 3.核心API:BeanInfo java 的描述信息,Introspect ...

  8. (转)java缓存技术,记录

    http://blog.csdn.net/madun/article/details/8569860 最近再ITEYE上看到关于讨论JAVA缓存技术的帖子比较多,自己不懂,所以上网大概搜了下,找到一篇 ...

  9. paip.java 架构师之路以及java高级技术

    paip.java 架构师之路以及java高级技术 1.    Annotation 设计模式... 概念满天飞.ORM,IOC,AOP. Validator lambda4j memcache. 对 ...

随机推荐

  1. codevs 2597 团伙

    时间限制: 1 s  空间限制: 128000 KB  题目等级 : 黄金 Gold 题目描述 Description 1920年的芝加哥,出现了一群强盗.如果两个强盗遇上了,那么他们要么是朋友,要么 ...

  2. SQL语句 多表基本操作

    创建四张表学生表:学号(Sno).姓名(Sname).性别(Ssex).年龄(Sage)教师表:教师编号(Tno).教师姓名(Tname)课程表:课程编号(Cno).课程名(Cname).教师编号(T ...

  3. dotnetbar入门

    1.下载dotnetbar组件 2.工具箱引用 3.项目引用 4.开始工作 //此处Form完整的名称是System.Windows.Forms.Form,表示FrmMain窗体类是继承于System ...

  4. ios中二维码的使用之一: 二维码的生成

    iOS在7之后,具备了原生的二维码生成API; 生成二维码的准备:  #import <CoreImage/CoreImage.h> 导入框架: 开始生成: //1- 创建过滤器 CIFi ...

  5. android复习第一天-----简单的android常识

    前言:要去面试了,这些天花一些事件把android中简单的知识点来串联的复习一下 1,android中的工程结构 src文件夹:存储android文件的源代码 gen文件夹:有工具自动生成,不要去修改 ...

  6. Volley使用指南第二回(来自developer.android)

    上一篇文章翻译了一下google的Volley官方文档,讲到了最基本的发送request.这一次我们来下一回:创建一个自定义RequestQueue. 这篇文章将会教你一步一步创建自己的Request ...

  7. LiLei&amp;HanMeiMei的隐式马尔可夫爱情

    一篇非常棒的隐马尔可夫入门文章...推荐! from: http://staffwww.dcs.shef.ac.uk/people/W.Liu/hmm.html

  8. 佛祖保佑,从来没有Bug

    <span style="font-size:14px;">// _ooOoo_ // o8888888o // 88" . "88 // (| - ...

  9. Idea下载后初始配置(windows环境下)

    专业版的intellij可以免费试用30天.为了以后开发方便,咱们需要下载专业版进行破解. 一.破解 安装过程中有个界面如下,咱们选择License server填上http://idea.itebl ...

  10. 使用OpenCV训练Haar like+Adaboost分类器的常见问题

    <FAQ:OpenCV Haartraining>——使用OpenCV训练Haar like+Adaboost分类器的常见问题 最近使用OpenCV训练Haar like+Adaboost ...