如何把Java代码玩出花?JVM Sandbox入门教程与原理浅谈

在日常业务代码开发中,我们经常接触到AOP,比如熟知的Spring AOP 。我们用它来做业务切面 , 比如登录校验,日志记录 , 性能监控,全局过滤器等 。但Spring AOP有一个局限性,并不是所有的类都托管在 Spring 容器中,例如很多中间件代码、三方包代码,Java原生代码,都不能被Spring AOP代理到 。如此一来 , 一旦你想要做的切面逻辑并不属于Spring的管辖范围,或者你想实现脱离Spring限制的切面功能,就无法实现了 。
那对于Java后端应用,有没有一种更为通用的AOP方式呢?答案是有的,Java自身提供了JVM TI,Instrumentation等功能 , 允许使用者以通过一系列API完成对JVM的复杂控制 。自此衍生出了很多著名的框架,比如Btrace,Arthas等等 , 帮助开发者们实现更多更复杂的Java功能 。
JVM Sandbox也是其中的一员 。当然,不同框架的设计目的和使命是不一样的,JVM-Sandbox的设计目的是实现一种在不重启、不侵入目标JVM应用情况下的AOP解决方案 。
是不是看到这里还是不清楚我在讲什么?别急 , 我举几个典型的JVM-Sandbox应用场景:

  • 流量回放:如何录制线上应用每次接口请求的入参和出参?改动应用代码固然可以,但成本太大 , 通过JVM-Sandbox,可以直接在不修改代码的情况下,直接抓取接口的出入参 。
  • 安全漏洞热修复:假设某个三方包(例如出名的fastjson)又出现了漏洞 , 集团内那么多应用,一个个发布新版本修复,漏洞已经造成了大量破坏 。通过JVM-Sandbox,直接修改替换有漏洞的代码,及时止损 。
  • 接口故障模拟:想要模拟某个接口超时5s后返回false的情况,JVM-Sandbox很轻松就能实现 。
  • 故障定位:像Arthas类似的功能 。
  • 接口限流:动态对指定的接口做限流 。
  • 日志打印
  • ...
可以看到,借助JVM-Sandbox,你可以实现很多之前在业务代码中做不了的事,大大拓展了可操作的范围 。
本文围绕JVM SandBox展开,主要介绍如下内容:
  • JVM SandBox诞生背景
  • JVM SandBox架构设计
  • JVM SandBox代码实战
  • JVM SandBox底层技术
  • 总结与展望
JVM Sandbox诞生背景JVM Sandbox诞生的技术背景在引言中已经赘述完毕,下面是作者开发该框架的一些业务背景,以下描述引用自文章:
JVM SandBox 是阿里开源的一款 JVM 平台非侵入式运行期 AOP 解决方案 , 本质上是一种 AOP 落地形式 。那么可能有同学会问:已有成熟的 Spring AOP 解决方案,阿里巴巴为什么还要“重复造轮子”?这个问题要回到 JVM SandBox 诞生的背景中来回答 。在 2016 年中,天猫双十一催动了阿里巴巴内部大量业务系统的改动,恰逢徐冬晨(阿里巴巴测试开发专家)所在的团队调整,测试资源保障严重不足 , 迫使他们必须考虑更精准、更便捷的老业务测试回归验证方案 。开发团队面临的是新接手的老系统,老的业务代码架构难以满足可测性的要求,很多现有测试框架也无法应用到老的业务系统架构中 , 于是需要新的测试思路和测试框架 。
为什么不采用 Spring AOP 方案呢?Spring AOP 方案的痛点在于不是所有业务代码都托管在 Spring 容器中,而且更底层的中间件代码、三方包代码无法纳入到回归测试范围,更糟糕的是测试框架会引入自身所依赖的类库,经常与业务代码的类库产生冲突,因此,JVM SandBox 应运而生 。
JVM Sandbox整体架构本章节不详细讲述JVM SandBox的所有架构设计 , 只讲其中几个最重要的特性 。详细的架构设计可以看原框架代码仓库的Wiki 。
类隔离很多框架通过破坏双亲委派(我更愿意称之为直系亲属委派)来实现类隔离 , SandBox也不例外 。它通过自定义的SandboxClassLoader破坏了双亲委派的约定,实现了几个隔离特性:
  • 和目标应用的类隔离:不用担心加载沙箱会引起原应用的类污染、冲突 。
  • 模块之间类隔离:做到模块与模块之间、模块和沙箱之间、模块和应用之间互不干扰 。

如何把Java代码玩出花?JVM Sandbox入门教程与原理浅谈

文章插图
无侵入AOP与事件驱动JVM-SANDBOX属于基于Instrumentation的动态编织类的AOP框架,通过精心构造了字节码增强逻辑,使得沙箱的模块能在不违反JDK约束情况下实现对目标应用方法的无侵入运行时AOP拦截 。
如何把Java代码玩出花?JVM Sandbox入门教程与原理浅谈

文章插图
从上图中 , 可以看到一个方法的整个执行周期都被代码“加强”了 , 能够带来的好处就是你在使用JVM SandBox只需要对于方法的事件进行处理 。

推荐阅读