如何把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只需要對于方法的事件進行處理 。

推薦閱讀