SandBox中的JavaAgent技術

8.1 JavaAgent

Java Agent 是一種強大的技術,在運行時動態修改已加載類的字節碼,為應用程序注入額外的功能和行為。

JDK 1.5 支持靜態 Instrumentation,基本的思路是在 JVM 啟動的時候添加一個代理(javaagent),每個代理是一個 jar 包,其 MANIFEST.MF 文件里指定了代理類,這個代理類包含一個 premain 方法。JVM 在類加載時候會先執行代理類的 premain 方法,再執行 Java 程序本身的 main 方法,這就是 premain 名字的來源。在 premain 方法中可以對加載前的 class 文件進行修改。

8.1.1 應用場景:

代碼注入:通過 Java Agent 技術,我們可以在運行時將自定義的字節碼注入到已加載的類中。這樣可以實現 AOP 編程思想,將通用的邏輯代碼動態地注入到目標類中,簡化代碼的編寫和維護。

性能監控:Java Agent 可以用于實時監控應用程序的性能指標,如方法的執行時間、方法的調用次數等。通過在方法的前后插入字節碼,我們可以收集這些信息,并進行實時監控、統計和分析,幫助優化和調優應用程序的性能。

調試工具:Java Agent 可以用作調試工具的基礎。我們可以通過動態修改字節碼,將額外的調試信息插入到目標類中,例如打印方法的參數、返回值等。這樣,在調試過程中可以更加方便地獲取和分析這些信息,幫助快速定位問題。

安全檢查:Java Agent 還可以用于實現安全檢查機制。通過對正在加載的類進行攔截和檢查,我們可以在運行時進行代碼審計、防止惡意代碼注入等,提高應用程序的安全性。

8.1.2 啟動方式

啟動掛載(Agent):

所有的類在加載時都會執行transform,我們在此方法中通過 Instrumentation 增強目標類。

隨著JVM啟動一起啟動(java -javaagent:(jar包名) (方法類名))

premain(): 實現premain方法,并且添加一個自定義transformer,把操作放在自定義的transformer內,該transformer要實現ClassFileTransformer.transform() 主程序運行時:加載每個類前都會進入transform(),可以獲取到它的加載器、類名、字節碼buffer等

動態掛載(Attach):

動態掛載之后,類加載時都會執行transform,我們在此方法中通過 Instrumentation 增強目標類。

動態掛載前 已經加載的類,都未經歷增強的處理。 可通過調用retransformClasses方法,讓已加載的類重新加載, 重新加載時也會執行transform,我們在此方法中增強目標類。

在已經運行的JVM進程中,動態的插入。通過attach API調用,在sandbox中執行./sandbox -p pid(目標 jvm 進程 id)是使用的 attach api 方式進行 agent 的掛載

agentmain():對于agentmain也是一樣的流程,但多一步inst.retransformClasses()的操作讓JVM重新加載修改過的類的字節碼,否則修改不會生效 使用com.sun.tools.attach.VirtualMachine進行動態掛載Agent:

 
private void attachAgentToTargetJVM() throws Exception {List<VirtualMachineDescriptor> virtualMachineDescriptors = VirtualMachine.list();VirtualMachineDescriptor targetVM = null;for (VirtualMachineDescriptor descriptor : virtualMachineDescriptors) {if (descriptor.id().equals(configure.getPid())) {targetVM = descriptor;break;}}if (targetVM == null) {throw new IllegalArgumentException("could not find the target jvm by process id:" + configure.getPid());}VirtualMachine virtualMachine = null;try {virtualMachine = VirtualMachine.attach(targetVM);virtualMachine.loadAgent("{agent}", "{params}");} catch (Exception e) {if (virtualMachine != null) {virtualMachine.detach();}}}

它的 addTransformer 給 Instrumentation 注冊一個 transformer,transformer 是 ClassFileTransformer 接口的實例,這個接口就只有一個 transform 方法,調用 addTransformer 設置 transformer 以后,后續JVM 加載所有類之前都會被這個 transform 方法攔截,這個方法接收原類文件的字節數組,返回轉換過的字節數組,在這個方法中可以做任意的類文件改寫。

8.1.3 JavaAgent使用demo

使用premain的方式進行javaAgent的啟動(不詳細展示對java類的增強demo)

首先在一個maven項目中創建我們的核心demo-AgentDemo

 
package com.xhz.demo;import java.lang.instrument.Instrumentation;/*** @version V1.0* @Author : xiehuizhi* @create 2023/12/20 14:33*/public class AgentDemo {public static void premain(String agentArgs, Instrumentation instrumentation){System.out.println(agentArgs+"============尊貴的xxxx===============");}public static void premain(String agentArgs){System.out.println(agentArgs+"============尊貴的xxxx================");}}

創建完成之后可以手動在resources中創建MANIFEST.MF文件(也可以在pom中配置)

 

Manifest-Version: 1.0

Premain-Class: com.xhz.demo.AgentDemo

Can-Redefine-Classes: true

Can-Retransform-Classes: true

?

pom配置:

 
<plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-jar-plugin</artifactId><version>3.1.2</version><configuration><archive><manifestEntries><Premain-Class>club.throwable.permain.PermainAgent</Premain-Class><Can-Redefine-Classes>true</Can-Redefine-Classes><Can-Retransform-Classes>true</Can-Retransform-Classes></manifestEntries></archive></configuration></plugin></plugins>

然后要實現agent的功能,需要將你的項目打成jar包

打包命令:mvn clean package

然后新建一個可以啟動的Main類

 
package Utils;/*** @version V1.0* @Author : xiehuizhi* @create 2023/12/20 14:29*/public class Main {public static void main(String[] args) {System.out.println("流量回放");}}

?

在springboot啟動項增加啟動參數

8.2 Sandbox啟動與Agent掛載的流程

sandbox-spy:這個包里的代碼是一系列的模板代碼,后期Sandbox會通過ASM框架將這些代碼轉化成字節碼增加到業務代碼的字節碼當中,實現對業務代碼的增強功能

但spy類為什么要被BootstrapClassLoader加載呢?我們不僅要增強業務代碼,也要增強JDK里面的代碼,將spy添加到BootstrapClassLoader的類路徑,只要不破壞雙親委托機制,都能夠被spy類增強,這是一種比較保險的做法。

8.3 JVM-SandBox實現字節碼增強

一般的Spring AOP:實現業務切面,針對于JAVA后端應用也需要AOP

JVM-Sandbox的設計目的是實現一種在不重啟、不侵入目標JVM應用情況下的AOP解決方案。

Jvm-SandBox字節碼增強流程梳理:

8.3.1 增強過程

8.3.2 實現字節碼增強邏輯

通過AsmMethods接口獲取Sandbox自定義Spy類完成字節碼增強

spy增強的靜態方法

JavaAgent的本質就是字節碼增強,這章主要介紹了Sandbox字節碼增強功能的核心邏輯,包括增強邏輯、SandboxClassFileTransformer類形變器、Spy增強的靜態方法。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/717393.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/717393.shtml
英文地址,請注明出處:http://en.pswp.cn/news/717393.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

基于阿里云OSS上傳圖片實戰案例

一、案例描述 基于Springboot框架實現一個上傳圖片到阿里云服務端保存的小案例。 二、準備工作 基于Springboot免費搭載輕量級阿里云OSS數據存儲庫&#xff08;將本地文本、照片、視頻、音頻等上傳云服務保存&#xff09;-CSDN博客 三、代碼 新建這兩個類&#xff1a;一個…

Golang函數make介紹和用法

1.介紹 golang分配內存主要有內置函數new和make 相同點: 他們的第一個參數都是一個類型而不是一個值 不同點: new可分配任意類型的數據make只能為slice, map, channel分配內存new返回的是指針make返回類型的是引用而不是指針,并且返回的值也依賴于具體傳入的類型, 這種不同點的…

C++原子操作

8.3.5 原子操作 在同一時刻只有唯一的線程對這個資源進行訪問。這有點類似互斥對象對共享資源的訪問的保護&#xff0c;但是原子操作更加接近底層&#xff0c;因而效率更高。 &#xff08;1&#xff09;pthread #include <stdatomic.h> atomic_int atomicVariable; at…

Python如何從SQL Server存取數據?

在Python中&#xff0c;你可以使用各種庫來連接和操作 SQL Server 數據庫。一種常用的庫是pyodbc&#xff0c;它是一個用于連接到各種數據庫的開源 Python 庫&#xff0c;包括 SQL Server。以下是連接到 SQL Server 并存取數據的基本步驟&#xff1a; 1、安裝 pyodbc 庫&#…

LANA: A Language-Capable Navigator for Instruction Following and Generation

摘要 最近&#xff0c;視覺語言導航&#xff08;VLN&#xff09;——要求機器人代理遵循導航指令——已經取得了巨大的進步。然而&#xff0c;現有文獻最強調將指令解釋為行動&#xff0c;只提供“愚蠢”的尋路代理。在本文中&#xff0c;我們設計了 LANA&#xff0c;一種支持…

【C++ 異常處理】

C 異常處理 ■ C 異常處理簡介■ throw (拋出異常)■ catch (捕獲異常)■ try&#xff08;&#xff09;■ C 標準的異常 ■ C 異常處理簡介 C 異常處理涉及到三個關鍵字&#xff1a;try、catch、throw。 屬性描述throw當問題出現時&#xff0c;程序會拋出一個異常。這是通過使…

【LeetCode-1143】最長公共子序列(動歸)

目錄 題目描述 解法1&#xff1a;動態規劃 代碼實現 題目鏈接 題目描述 給定兩個字符串 text1 和 text2&#xff0c;返回這兩個字符串的最長公共子序列的長度。 一個字符串的 子序列 是指這樣一個新的字符串&#xff1a;它是由原字符串在不改變字符的相對順序的情況下刪除…

Linux系統這些壓測工具,你用過嗎?

作為一名運維人員,你是否遇到過這種場景?需要用工具測試系統cpu或內存占用高來觸發告警,或者通過壓測測試服務的并發能力。作為運維工程師,也可以通過這些命令復現故障場景。那么通過本文可以讓你掌握常用的測試命令和工具。 更多技術博客,請關注微信公眾號:運維之美 一、…

LIDAR2Camera 手動標定

參考&#xff1a;搞懂了&#xff01;原來激光雷達和相機的內外參是這樣標定的_嗶哩嗶哩_bilibili 代碼下載&#xff1a;SensorsCalibration/lidar2camera at master PJLab-ADG/SensorsCalibration (github.com)

社區店選址評估:利用大數據選址的技巧與策略

在當今數字化的時代&#xff0c;利用大數據進行社區店選址評估已成為一種高效、科學的方法。作為一名開鮮奶吧5年的創業者&#xff0c;我將分享一些利用大數據選址的技巧與策略&#xff0c;幫助你找到最適合的店鋪位置。 1、確定目標商圈 在選址之前&#xff0c;首先要明確自己…

涉及主頁面內嵌iframe中的列表數據的保存

場景&#xff1a;主表 : 附表 1 : m&#xff0c;同一個頁面&#xff0c;共同使用一個保存按鈕進行兩個表的數據保存&#xff0c;頁面中間有個查詢按鈕&#xff0c;可以對子iframe頁面的內容進行刷新 流程項目頁面內嵌了個子iframe&#xff0c;項目頁面表單數據提交保存是一個…

爬蟲的一些小技巧總結

一、在爬蟲中&#xff0c;爬取的數據類型如下 1.document:返回的是一個HTML文檔 2.png:無損的圖片&#xff0c;jpg:壓縮后的圖片,wbep:有損壓縮&#xff0c;比png差&#xff0c;比jpg好 3.avgxml圖像編碼字符串 4.script:腳本文件&#xff0c;依據一定格式編寫的可執行的文…

【大廠AI課學習筆記NO.58】(11)混淆矩陣

混淆矩陣&#xff08;confusion matrix&#xff09;—— 混淆矩陣&#xff08;Confusion Matrix&#xff09;是人工智能領域&#xff0c;特別是在機器學習和深度學習中&#xff0c;用于衡量分類模型性能的重要工具。它通過統計分類模型的真實分類與預測分類之間的結果&#xf…

【python debug】python常見編譯問題解決方法_2

序言 記錄python使用過程中碰到的一些問題及其解決方法上一篇&#xff1a;python常見編譯問題解決方法_1 1. PermissionError: [Errno 13] Permission denied: ‘/lostfound’ 修改前&#xff1a; 修改后&#xff08;解決&#xff09;&#xff1a; 此外&#xff0c;可能文件夾…

leetcode 熱題 100_接雨水

題解一&#xff1a; 按列求&#xff1a;分別考慮每一列的雨水高度&#xff0c;某列的雨水高度只與其左側最高墻和右側最高墻有關&#xff0c;一種情況是該列比左右側的墻都低&#xff0c;則根據木桶效應該列雨水高度為min(左側墻高&#xff0c;右側墻高)-列高&#xff0c;而其余…

智能駕駛及相關零部件攝像頭毫米波雷達激光雷達和芯片滲透率

一、總體情況 乘聯會數據顯示&#xff0c;1月1日至1月28日&#xff0c;全國乘用車廠商新能源車批發銷量為56.7萬輛&#xff0c;同比增長76%&#xff0c;環比下降38%&#xff1b;國內新能源車市場零售銷量為59.6萬輛&#xff0c;同比增長92%&#xff0c;環比下降24%。 二、銷…

考研總計劃(基礎篇)

分為數學&#xff0c;專業課&#xff0c;英語三個部分 數學規劃表 高數基礎&#xff1a;3月初到4月15號 具體實行計劃&#xff1a;分為看課日和寫題日 看課日:早上10點到12點半看課&#xff0c;19:30到21:30繼續看課。 寫題日:早上10點到12點半復習前一天的題目&#xff0…

【word】引用文獻如何標注右上角

一、在Word文檔中引用文獻并標注在右上角的具體步驟如下 1、將光標移動到需要添加文獻標注的位置&#xff1a; 2、在文檔上方的工具欄中選擇“引用”選項&#xff1a; 3、點擊“插入腳注”或“插入尾注”&#xff1a; ①如果選擇的是腳注&#xff0c;則腳注區域會出現在本頁的…

多路轉接之epoll

常用的三個API&#xff1a; epoll_create(); //例如 int epfd epoll(10);創建一棵有10個結點的紅黑樹&#xff0c;注意&#xff1a;這個數只是對內核建議的數值&#xff0c;內核參照這個參數去構建epoll_ctrl();//參數2 op可以取值 EPOLL_CTL_ADD/MOD/DELevents:EPOLLIN/…

Professor教誨-學術筆記1

關于指導學生 自己帶的學生&#xff0c;要把文章從頭到尾檢查好了&#xff0c;再發給professor要至少留給professor一周的時間改文章&#xff0c;太遲了不如放棄DDL要在合作中&#xff0c;充分尊重合作者認真對待向別人求推薦信這件事&#xff0c;別人找你推薦也要慎重&#x…