欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

用rust?寫一個jar包?class沖突檢測工具

 更新時間:2023年05月24日 08:24:52   作者:Aitozi  
這篇文章主要介紹了用rust?寫一個jar包?class沖突檢測工具?的相關(guān)資料,需要的朋友可以參考下

Rust很適合寫命令行工具,特別是使用clap crate 更加方便,這篇文章介紹使用rust寫一個jar包class沖突檢測的工具。項目地址: https://github.com/Aitozi/jar_conflict_detector

首先jar包class沖突的現(xiàn)象是多個jar包中有同名的class,并且class的md5還不一樣,那么就意味著該class存在多個版本,那么就存在沖突的可能。

思路比較簡單,就是遍歷每個jar包,記錄ClassName 和 對應 CRC 校驗碼 及 jar 包的對應關(guān)系。

通過clap的derive api就可以快速定義個命令行的參數(shù)解析器。

#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)]
struct Args {
#[arg(
short,
long = "jars",
required = true,
help = "The jar list joined by semicolon"
)]
jar_list: String,
#[arg(long, help = "Disable the crc check", action = clap::ArgAction::SetTrue)]
#[arg(default_value_t = false)]
disable_crc: bool,
#[arg(short, long, action = clap::ArgAction::Append, help = "The exclude package prefix")]
exclude: Vec<String>,
}

通過zip讀取jar包中的entry, 過濾只處理.class文件,并從zip_file中讀取crc32的元數(shù)據(jù),這樣可以避免讀取原始數(shù)據(jù)生成md5,可以大大加快處理速度。
中間編寫的時候遇到了一個常見的rust borrow checker的問題。

以下代碼為例

fn main() {
let path = "/tmp/a.jar";
let jar = File::open(path).unwrap();
let mut zip = ZipArchive::new(jar).unwrap();


for name in zip.file_names() {
let entry = zip.by_name(name);
println!("name: {}, size: {}", name, entry.unwrap().size());
}
}

我是想通過遍歷ZipArchive#file_names然后根據(jù)文件名獲取ZipFile但是會有如下編譯錯誤

pub fn file_names(&self) -> impl Iterator<Item = &str> {
self.shared.names_map.keys().map(|s| s.as_str())
}
/// Search for a file entry by name
pub fn by_name<'a>(&'a mut self, name: &str) -> ZipResult<ZipFile<'a>> {
Ok(self.by_name_with_optional_password(name, None)?.unwrap())
}

但是用以下的方式就沒有問題

let path = "/tmp/a.jar";
let jar = File::open(path).unwrap();
let mut zip = ZipArchive::new(jar).unwrap();

for i in 0..zip.len() {
let entry = zip.by_index(i).unwrap();
println!("name: {}, size: {}", entry.name(), entry.size());
}

這里我比較奇怪的是從方法簽名上看 len() 和 file_names()都會發(fā)生immutable borrow,而后面by_index 和 by_name都會發(fā)生mutable borrow。為什么會一個可以通過檢查,一個不行。

pub fn len(&self) -> usize {
self.shared.files.len()
}

len函數(shù)實際的簽名應該是fn len<'a>(&'a self) -> usize 返回值是usize,所以函數(shù)調(diào)用完成后就不再和借用有關(guān)了。所以 immutable borrow 就結(jié)束了。
file_names實際簽名是fn file_names<'a>(&'a self) -> impl Iterator<Item = &'a str> {…}返回值的生命周期和 入?yún)⒌?immutable ref周期相同,所以后續(xù)就檢測出同時存在可變和不可變引用了。

詳細解釋: https://users.rust-lang.org/t/borrow-check-understanding/94260/2

命令行頻繁被Killed問題

問題現(xiàn)象是當使用cargo build打包出binary后,通過cp 到 /tmp/jcd執(zhí)行 會出現(xiàn) Killed的情況,不是必現(xiàn),但是當出現(xiàn)之后后續(xù)就一直會這樣,百思不得其解。

$ /tmp/jcd
[1] 16957 killed /tmp/jcd

后通過在rust user 論壇提問找到答案,不得不說回復效率很高。
https://users.rust-lang.org/t/rust-command-line-tools-keeps-beeing-killed/94179原因應該是和蘋果電腦上的 Code sign機制有關(guān),在蘋果沒有解決這個問題之前,建議通過ditto替代cp命令來copy程序。

經(jīng)過檢查系統(tǒng)日志確實有出現(xiàn) Code Signature Invalid的報錯

相同的Class CRC和MD5卻不一樣

問題是發(fā)現(xiàn)在集成這個工具到內(nèi)部的插件框架中,集成過程中發(fā)現(xiàn)一個Jar包被另一個module依賴,經(jīng)過shade插件打包(沒有對相關(guān)class進行relocate) 后,生成的class crc32不同,被識別為會沖突的類。通過javap -v 查看兩個class對比發(fā)現(xiàn)里面的僅僅是一些constant pool 不同。

那么懷疑就是maven-shade-plugin 做了什么操作,翻閱了下代碼,查看了shade的處理流程.

看到以下這段,發(fā)現(xiàn)這不就是我遇到的問題么。

查閱了相應的issue: https://issues.apache.org/jira/browse/MSHADE-391在3.3.0 才解決,而我使用的版本正好是3.2.4。升級插件重新生成校驗碼一致了。

解決沖突的Class

最后再回到最初的目的,當我們通過工具檢測出沖突的class應該怎么解決呢。

首先我們需要判斷這個class是否是運行時所需要的。

如果不是所需要的那么我們就應該直接排掉他,排除有兩種手段(這里針對的是maven shade的打包方式),如果在dependency tree中可以看到相應package的依賴,那么可以直接通過如下的白名單 include 或者 exclude 掉某個 artifact。

<artifactSet combine.self="override">
<includes>
<include>commons-dbcp:commons-dbcp</include>
<include>commons-pool:commons-pool</include>
<include>mysql:mysql-connector-java</include>
</includes>
</artifactSet>

但是不排除這個依賴包本身就是fatjar,那么直接通過這種方式就排不掉這個依賴,可以通過filters 配置文件 粒度的匹配過濾

<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
<exclude>javax/**</exclude>
<exclude>org/apache/flink/fnexecution/**</exclude>
<exclde>org/slf4j/**</exclde>
</excludes>
</filter>
</filters>

如果這個沖突的class是運行時需要的,那么可以通過relocation的方式給各自的插件包中shade成帶特殊前綴的class名,解決同名沖突。

<relocation>
<pattern>org.apache.http</pattern>
<shadedPattern>com.alipay.flink.sls.shaded.org.apache.http</shadedPattern>
</relocation>

到此這篇關(guān)于用rust 寫一個jar包 class沖突檢測工具 的文章就介紹到這了,更多相關(guān)rust 寫jar包 class沖突檢測工具 內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Rust  利用 chrono 庫實現(xiàn)日期和字符串互相轉(zhuǎn)換的示例

    Rust  利用 chrono 庫實現(xiàn)日期和字符串互相轉(zhuǎn)換的示例

    在Rust中,chrono庫提供了強大的日期和時間處理功能,使得日期與字符串之間的轉(zhuǎn)換變得簡單,本文介紹了如何在Rust中使用chrono庫將日期轉(zhuǎn)換成字符串,以及如何將字符串解析為日期,對于需要進行日期時間格式化、解析或進行時區(qū)處理的開發(fā)者來說,chrono庫是一個不可或缺的工具
    2024-11-11
  • Rust 數(shù)據(jù)類型詳解

    Rust 數(shù)據(jù)類型詳解

    本文介紹了Rust編程語言中的標量類型和復合類型,標量類型包括整數(shù)、浮點數(shù)、布爾和字符,而復合類型則包括元組和數(shù)組,標量類型用于表示單個值,具有不同的表示和范圍,本文介紹的非常詳細,感興趣的朋友一起看看吧
    2025-01-01
  • Rust?搭建一個小程序運行環(huán)境的方法詳解

    Rust?搭建一個小程序運行環(huán)境的方法詳解

    rust是一門比較新的編程語言,2015年5月15日,Rust編程語言核心團隊正式宣布發(fā)布Rust?1.0版本,本文給大家介紹Rust?搭建一個小程序運行環(huán)境,以iOS?為例介紹開發(fā)環(huán)境的準備,感興趣的朋友跟隨小編一起看看吧
    2022-05-05
  • Windows系統(tǒng)下安裝Rust環(huán)境超詳細教程

    Windows系統(tǒng)下安裝Rust環(huán)境超詳細教程

    這篇文章主要介紹了如何在Windows系統(tǒng)上安裝mingw64和Rust,mingw64是一個輕便的C語言編譯環(huán)境,可以替代Rust默認使用的Visual?Studio,文中通過圖文介紹的非常詳細,需要的朋友可以參考下
    2025-02-02
  • 詳解Rust中三種循環(huán)(loop,while,for)的使用

    詳解Rust中三種循環(huán)(loop,while,for)的使用

    我們常常需要重復執(zhí)行同一段代碼,針對這種場景,Rust?提供了多種循環(huán)(loop)工具。一個循環(huán)會執(zhí)行循環(huán)體中的代碼直到結(jié)尾,并緊接著回到開頭繼續(xù)執(zhí)行。而?Rust?提供了?3?種循環(huán):loop、while?和?for,下面逐一講解
    2022-09-09
  • Rust 配置文件內(nèi)容及使用全面講解

    Rust 配置文件內(nèi)容及使用全面講解

    這篇文章主要為大家介紹了Rust 配置文件內(nèi)容及使用全面講解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-10-10
  • Rust?中?Deref?Coercion講解

    Rust?中?Deref?Coercion講解

    Rust 的設(shè)計理念一向是顯式比隱式好,也就是說所有的行為盡量在代碼中表現(xiàn)出來,這篇文章主要介紹了Rust?中?Deref?Coercion?介紹,需要的朋友可以參考下
    2022-10-10
  • 一步到位,教你如何在Windows成功安裝Rust

    一步到位,教你如何在Windows成功安裝Rust

    一步到位:輕松學會在Windows上安裝Rust!想快速掌握Rust編程語言?別再為復雜教程頭疼!這份指南將手把手帶你順利完成Windows平臺上的Rust安裝全過程,從此編碼之旅更加順暢無阻,立即閱讀,開始你的Rust編程旅程吧!
    2024-01-01
  • 深入探究在Rust中函數(shù)、方法和關(guān)聯(lián)函數(shù)有什么區(qū)別

    深入探究在Rust中函數(shù)、方法和關(guān)聯(lián)函數(shù)有什么區(qū)別

    在 Rust 中,函數(shù)、方法和關(guān)聯(lián)函數(shù)都是用來封裝行為的,它們之間的區(qū)別主要在于它們的定義和調(diào)用方式,本文將通過一個簡單的rust代碼示例來給大家講講Rust中函數(shù)、方法和關(guān)聯(lián)函數(shù)區(qū)別,需要的朋友可以參考下
    2023-08-08
  • 詳解rust?自動化測試、迭代器與閉包、智能指針、無畏并發(fā)

    詳解rust?自動化測試、迭代器與閉包、智能指針、無畏并發(fā)

    這篇文章主要介紹了rust?自動化測試、迭代器與閉包、智能指針、無畏并發(fā),本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-11-11

最新評論