歡迎光臨
每天分享高質量文章

Java黑科技之源:JVMTI完全解讀

        Java生態中有一些非常規的技術,它們能達到一些特別的效果。這些技術的實現原理不去深究的話一般並不是廣為人知。這種技術通常被稱為黑科技。而這些黑科技中的絕大部分底層都是通過JVMTI實現的。

形象地說,JVMTI是Java虛擬機提供的一整套後門。通過這套後門可以對虛擬機方方面面進行監控,分析。甚至干預虛擬機的運行。

下麵先介紹下哪些黑科技是通過JVMTI實現的,再詳細的介紹JVMTI。

 


JVMTI可以用來實現哪些黑科技

  1. 使用JVMTI對class檔案加密

    有時一些涉及到關鍵技術的class檔案或者jar包我們不希望對外暴露,因而需要進行加密。使用一些常規的手段(例如使用混淆器或者自定義類加載器)來對class檔案進行加密很容易被反編譯。反編譯後的代碼雖然增加了閱讀的難度,但花費一些功夫也是可以讀懂的。使用JVMTI我們可以將解密的代碼封裝成.dll,或.so 檔案。這些檔案想要反編譯就很麻煩了,另外還能加殼。解密代碼不能被破解,從而也就保護了我們想要加密的class檔案。

     

  2. 使用JVMTI實現應用性能監控(APM)

    在微服務大行其道的環境下,分佈式系統的邏輯結構變得越來越複雜。這給系統性能分析和問題定位帶來了非常大的挑戰。基於JVMTI的APM能夠解決分佈式架構和微服務帶來的監控和運維上的挑戰。APM通過匯聚業務系統各處理環節的實時資料,分析業務系統各事務處理的交易路徑和處理時間,實現對應用的全鏈路性能監測。開源的Pinpoint, ZipKin, Hawkular,商業的AppDynamics,OneAPM,Google Dapper等都是個中好手。

     

  3. 產品運行時錯誤監測及除錯

    想要看生產環境的異常,最原始的方式是登錄到生產環境的機器查看日誌。稍微高級一點的方式是通過日誌監控或者APM等工具將異常採集上來。但是這些手段都有許多明顯的缺點。首先,不是所有的異常都會被打印到日誌中,有些異常可能被代碼吃掉了;其次,打印異常的時候通常只有異常堆棧信息,異常發生時背景關係的變數值很難獲取到(除非有經驗的程式員將其打印出來了),而這些信息對定位異常的原因至關重要。基於JVMTI可以開發出一款工具來時事監控生產環境的異常。這方面有一款成熟的商業軟體OverOps,其有三個主要的功能:1. 採集到所有的異常,包括try catch之後沒有打印出來的異常;2. 可以採集到異常發生時背景關係所有變數的值;3. 可以將異常發生的堆棧對應的原始碼採集展示出來,從而在一個系統上就可以看代碼定位問題,不需要打開ide除錯原始碼。

     

  4. JAVA程式的除錯(debug)。

    一般JAVA的IDE都自帶了除錯工具。例如Eclipse的除錯器相信大部分人都使用過。它的除錯器org.eclipse.jdt.debug插件底層就是呼叫的JVMTI來實現的。不僅如此,隨著服務雲化的發展,google甚至推出了雲端除錯工具cloud debugger。它時一個web應用,可以直接對生產環境進行遠程除錯,不需要重啟或者中斷服務。阿裡也有類似的工具Zdebugger。

     

  5. JAVA程式的診斷(profile)。

    當出現cpu使用率過高、執行緒死鎖等問題時,需要使用一些JAVA性能剖析或者診斷工具來分析具體的原因。例如Alibaba開源的Java診斷工具Arthas,深受開發者喜愛。Arthas的功能十分強大,它可以查看或者動態修改某個變數的值、統計某個方法呼叫鏈上的耗時、攔截方法前後,打印引數值和傳回值,以及異常信息等。

     

  6. 熱加載

    熱加載指的是在不重啟虛擬機的情況下重新加載一些class。熱加載可以使本地除錯代碼非常節省時間,不用每次更新代碼都重啟一邊程式。同時,在一線不方便重啟的線上環境也能派上用場。這方面的代表產品有商業產品JRebel等。JRebel能夠對應用中的任何class起作用。


JVMTI是什麼

  1. JVMTI的定義及原理

    在介紹JVMTI之前,需要先瞭解下Java平臺除錯體系JPDA(Java PlatformDebugger Architecture)。它是Java虛擬機為除錯和監控虛擬機專門提供的一套接口。如下圖所示,JPDA被抽象為三層實現。其中JVMTI就是JVM對外暴露的接口。JDI是實現了JDWP通信協議的客戶端,除錯器通過它和JVM中被除錯程式通信。

    JVMTI 本質上是在JVM內部的許多事件進行了埋點。通過這些埋點可以給外部提供當前背景關係的一些信息。甚至可以接受外部的命令來改變下一步的動作。外部程式一般利用C/C++實現一個JVMTIAgent,在Agent裡面註冊一些JVM事件的回呼。當事件發生時JVMTI呼叫這些回呼方法。Agent可以在回呼方法裡面實現自己的邏輯。JVMTIAgent是以動態鏈接庫的形式被虛擬機加載的。

     

     

     

     

  2. JVMTI的歷史

    JVMTI 的前身是JVMDI(Java Virtual Machine Profiler Interface) 和 JVMPI(Java Virtual Machine Debug Interface),它們原來分別被用於提供除錯 Java 程式以及 Java 程式調節性能的功能。在 J2SE 5.0 之後 JDK 取代了JVMDI 和 JVMPI 這兩套接口,JVMDI 在最新的 Java SE 6 中已經不提供支持,而 JVMPI 也計劃在 Java SE 7 後被徹底取代。

     

  3. JVMTI的功能

    JVMTI處於整個JPDA 體系的最底層,所有除錯功能本質上都需要通過 JVMTI 來提供。從大的方面來說,JVMTI 提供了可用於 debug 和profiler 的接口;同時,在 Java 5/6 中,虛擬機接口也增加了監聽(Monitoring),執行緒分析(Thread analysis)以及改寫率分析(Coverage Analysis)等功能。從小的方面來說包含了虛擬機中執行緒、記憶體、堆、棧、類、方法、變數,事件、定時器處理等等諸多功能。具體可以參考oracle 的文件:https://docs.oracle.com/javase/1.5.0/docs/guide/jvmti/jvmti.html。通過這些接口,開發人員不僅可以除錯在該虛擬機上運行的 Java 程式,還能查看它們運行的狀態,設置回呼函式,控制某些環境變數,從而優化程式性能。

     

  4. JVMTI的實現

    JVMTI 並不一定在所有的 Java 虛擬機上都有實現,不同的虛擬機的實現也不盡相同。不過在一些主流的虛擬機中,比如 Sun 和 IBM,以及一些開源的如Apache Harmony DRLVM 中,都提供了標準 JVMTI 實現。

參考:

  1. https://docs.oracle.com/javase/1.5.0/docs/guide/jvmti/jvmti.html
  2. https://www.ibm.com/developerworks/cn/java/j-lo-jpda2/
  3. http://blog.caoxudong.info/blog/2017/12/07/jvmti_reference
  4. http://lovestblog.cn/blog/2015/09/14/javaagent/
  5. https://www.jianshu.com/p/e59c4eed44a2

 


    已同步到看一看
    赞(0)

    分享創造快樂