1. 程式人生 > >Java Agent與Native Agent的利與弊

Java Agent與Native Agent的利與弊

許多應用效能管理(APM)廠商在對 JVM執行時效能進行深入分析時,一般使用JVM執行時的介面,而JVM執行時提供兩種介面:JVMPT和JVMTI。JVMPI 介面從 Java 5後逐漸被JVMTI 所取代,且JVMTI介面都允許APM廠商將本地庫(通常稱作Native Agent)載入到與JVM 同一個程序中,使得該本地庫可以通過本地的 API (C/C++程式碼)訪問JVM 執行時的狀態和應用程式的效能資料。另外,由於該庫並不作為JVM 執行時的一部分,它不會受到JVM 停止的影響(例如:較長的垃圾收集掛起、執行時錯誤等),因此能夠一直向外部工具傳輸資料。

Java 5 還引入了一種純 Java 介面方案(通常稱作Java Agent),作為這種本地介面的替代方案。這種方案允許將Java Agent載入到JVM 之中,並作為JVM 的一部分執行。其“不利”的一面是,Jva Agent是在JVM 啟動後期才被載入,該Agent是執行在JVM執行時的容器裡,它會受到JVM 掛起或 Java 執行時問題的影響,並且不能報告某些型別的錯誤資訊。

在本部落格中我們將主要闡述,為何Dynatrace的工程團隊決定採用Native Agent方式結合位元組碼插碼技術(bytecode instrumentation,BCI)的方式,而不是採用基於 Java Agent的方式,來監控應用程式的效能。

對所有的類進行全面、深入的分析

Native Agent能夠在任何類載入之前載入。這使Native Agent能夠從一開始就採集資料,並可使其不會受到任何約束的,對所有的 Java 程式碼進行資料採集和控制執行。為能捕獲方法級的資訊,可利用位元組碼插碼技術(BCI)實現優勢互補,而不是依賴於Native介面的回撥。這樣不僅能對任何類執行位元組碼插碼,還能對核心系統類進行深入分析(java.lang.Object、java.lang.Thread等)。

獲得更為詳盡的資訊

通過JVM native介面,我們可以獲得更為詳盡的效能資訊,例如作業系統的高精度時鐘、詳細的垃圾收集資料等。由於採用了Native Agent方式,因此不必另外安裝用於採集系統資訊的程式。而Java Agent很可能無法訪問上述資料,因為它運行於JVM 內的特殊的安全背景環境之中。
JVM

獲取其他資訊

在Native Agent內部,我們可以採集到與JVM 有關的大量資訊,例如記憶體、執行緒、JVM 崩潰等。尤其對於執行緒和記憶體分析,訪問JVM 執行緒和記憶體使用情況以及本地執行緒和記憶體使用情況有助於效能監測。一旦出現記憶體不足錯誤導致崩潰,因為本地程序仍在執行,所以Native Agent仍能採集堆疊中的資料和記憶體資訊。
【執行緒死鎖分析】
Thread


【記憶體洩露分析】
Memory

對 JVM 的影響輕微

通過原生代碼呼叫JVMTI介面,可以更加有效的獲取效能分析的資料,例如,通過執行緒快照(Thread Snapshot)的方式獲取執行緒棧資訊,而從JVM 內部的Java Agent呼叫JVMTI介面獲取此類資訊所需的代價要高很多,然而,對執行緒棧做快照恰恰是定位Java方法執行緩慢的最佳途徑,由於對JVM的負載太高,以至於部分Java Agent的APM廠商不得不放棄此功能來達到使用者對效能開銷的要求。
Callstack

未掛靠 JVM

由於Native Agent沒有掛靠(attach)在 JVM 上,因此不會受到 JVM 掛起(特別是與垃圾收集)的影響,可以在JVM 停止(但程序仍然執行)期間仍採集資料,這樣可以幫助我們採集有關垃圾回收所導致的JVM掛起對當前正在執行應用執行緒的實際影響的資訊,而 Java Agent則無法獲得這樣的資訊,因為它也會受到JVM掛起的影響而暫停收集資料。

總結

Native Agent因為工作原理的不同,導致其與Java Agent相比,擁有明顯的優勢,具體總結如下:
1. 獲取JVM執行時的效能引數。
2. 獲取JVM執行緒方法呼叫棧資訊
3. 不受JVM的執行狀態影響。
4. 開銷更少