java 使用本机代理_Java与本机代理–他们所做的强大功能
java 使用本機代理
在安裝代理之前應了解的內容及其對代碼的影響
在構建可伸縮的服務器端應用程序時,我們花費大量時間思考如何在生產中監視,操作和更新代碼。 已經開發出一種新的工具來幫助Java和Scala開發人員做到這一點。 它們中的許多都是建立在最強大的方式之一上的,即外部代碼可以在運行時與JVM集成的Java代理 。
代理是OS本機或Java庫(我們將在下面描述它們之間的差異),JVM提供的這些功能是普通應用程序代碼所不具備的。 為了了解它們的基本原理,讓我們看一下我們使用的依賴它們的一些工具–
- 探查器使用Java代理修改目標框架的代碼,以注入收集性能指標的新代碼。 這包括獨立或托管服務,例如NewRelic或YourKit。
- Play框架 V1使用Java代理在運行時啟用類的熱交換。
- JRebel通過構建一種可以在運行時提供平滑的類熱交換而無需重新啟動JVM的技術,將其帶入了一個新的高度。
- 在Takipi,我們利用JVM提供給本機代理的低級功能來顯示導致錯誤的實際源代碼和變量值。
代理商可以做什么?
正如我上面提到的,有兩種代理-Java和本機。 兩者以幾乎相同的方式(使用特殊的JVM啟動參數)加載到JVM中時,它們的構建方式和用途幾乎完全不同。
讓我們看一下兩個–
Java代理
Java代理是.jar文件,它們定義了一個特殊的premain靜態函數,在調用應用程序的主函數之前,JVM將先調用該靜態函數。 神奇的部分來自Instrumentation對象,該對象由主機JVM作為參數傳遞給該函數。 通過保留該對象,代理程序的代碼(否則,其行為就像由根類加載器加載的任何Java代碼一樣)可以做一些真正強大的事情。
public static void premain(String agentArgs, Instrumentation inst) { myInst = inst; //grab a reference to the inst object for use later }他們做什么 。 賦予代理程序最強大的功能是在運行時類(字段結構是不可變的)上動態重寫目標類方法內容的能力。 此過程稱為字節碼檢測,使代理能夠在代碼運行時實質上重寫方法的內容。
一些示例包括添加對特定方法的調用以概要分析性能(例如,結束時間–開始時間)或記錄參數值(例如,傳遞給Servlet的URL)。 另一個示例將是重新加載類的新版本,而不用像JRebel那樣重新啟動JVM。
怎么做的 。 對于代理修改代碼或已加載的類,它實際上觸發了JVM重新加載類的過程,其中該類的字節碼被替換為新版本。 這就要求代理能夠為JVM提供可驗證的新字節碼(即符合JVM規范)。 不幸的是,在運行時生成正確的字節碼并不是一件容易的事–有很多要求和邊緣情況。 對于這種代理,通常使用一個庫來讀取和寫入字節碼,從而使他們能夠將現有類的字節碼加載到類似DOM的結構中,通過添加性能分析調用之類的東西對其進行修改,然后將DOM保存回原始字節碼。 ASM對此很受歡迎。 如此流行,以至于Sun的一些內部代碼實際上已使用它來解析Java中的字節碼。
本地代理
本地代理人是完全不同的野獸。 如果您認為Java代理可以讓您做一些很酷的事情,那么請堅持一下,因為本機代理在不同的層次上運行。 本機代理不是用Java編寫的,而是大多數用C ++編寫的,并且不受常規Java代碼操作的規則和限制的約束。 不僅如此,它們還具有稱為JVM工具接口(JVMTI)的極其強大的功能集。
他們做什么 。 jvmti.h公開的這組API實質上使JVM動態加載的C ++庫能夠獲得對JVM實時工作的極高可見性。 這涵蓋了廣泛的領域,包括GC,鎖定,代碼操作,同步,線程管理,編譯調試等等。
JVM TI旨在使JVM盡可能透明,同時仍保持設計靈活性,以允許JVM供應商提供不同的基礎實現。 這套API非常廣泛,實際上包含了數百個JVM回調和函數。 您可以使用它們來執行Java代理無法完成的極其強大的功能,例如編寫您自己的調試器或構建底層的實時錯誤分析工具( Takipi就是這樣)。
例如,這是JVMTI提供給代理的回調,因此,只要在JVM內部的任何地方引發異常,代理都會收到引發異常的字節碼位置,所有者線程,異常對象和如果/在哪里被捕獲。 確實功能強大。
void JNICALL ExceptionCallback(jvmtiEnv *jvmti, JNIEnv *jni, jthread thread, jmethodID method, jlocation location, jobject exception, jmethodID catch_method, jlocation catch_location)缺點 。 如果我描述的所有內容聽起來都像桃子一樣,您可以問為什么不是所有代理都寫成本地代理? 沒有什么理由可以知道,因此這里是(沒有特定的順序)。
復雜性 。 首先是JVMTI API非常復雜,帶有許多小的移動輪子。在大多數情況下,如果您不連接需要非常低級功能的代理,則可以使用Java代理API很好。更直接,可以幫助您更快地完成工作。
可移植性 。 由于本機代理是作為本機庫(.so / .dll)編寫和編譯的,因此需要在要支持的任何數量的操作系統上進行編譯和測試。 如果您查看Windows,OSX和Linux帶來的不同風格,則可以轉化為大量工作。 將其與Java代理(由JVM作為Java代碼執行,因此在設計上具有固有的可移植性)進行比較。
字節碼操作。 由于本機代理程序通常是用C ++編寫的,這意味著它們不能直接使用經過嘗試的真正的Java字節碼操作庫(例如ASM),而不必使用JNI返回JVM,這確實會帶來一些樂趣。
穩定性 。 JVM提供了強有力的保護措施,以防止代碼執行可能導致憤怒的OS終止進程的事情。 在正常情況下,內存訪問沖突會導致SIGSEV并使程序崩潰,請給我們包裝一個不錯的NullPointerException。 由于本機代理程序在JVM的相同級別上運行(與Java代理程序由其執行代碼)相同,因此它們所犯的任何錯誤都可能會終止JVM。
希望這有助于突出兩種之間的某些區別。 了解什么是代理以及它們是如何構建的,這是很好的,即使您從未最終編寫過代理,也可能依靠其中的一個或多個來為您的應用程序提供動力。
翻譯自: https://www.javacodegeeks.com/2014/01/java-vs-native-agents-the-powerful-things-they-do.html
java 使用本機代理
總結
以上是生活随笔為你收集整理的java 使用本机代理_Java与本机代理–他们所做的强大功能的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 京东、阿里重回战场,社区团购为何让大厂们
- 下一篇: 在任何无法理解的情况下,请编写脚本