最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java解析嵌套jar中class文件過程

 更新時間:2026年04月22日 08:33:51   作者:繡花針  
本文介紹了兩種解析嵌套jar中的class文件的方式,一種是使用`spring-boot-loader`中的`JarFileArchive`,另一種是使用`JarFile`,通過實測對比了兩種方式的性能差異,結(jié)果表明`JarFile`方式略慢于`JarFileArchive`方式

一、簡述

Maven項目通過package打成jar包后,jar包中包含所有依賴lib文件。

本文介紹了兩種方式解析嵌套jar中的class文件,一種是通過spring-boot-loader包JarFileArchive,另一種是util包中JarFile。

二、JarFileArchive方式

1.spring-boot-loader依賴引入

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-loader</artifactId>
    <version>2.2.4.RELEASE</version>
</dependency>

2.demo案例

不同版本的spring-boot-loader,getNestedArchives(EntryFilter filter)有所變化(高版本中已廢棄,使用getNestedArchives(EntryFilter searchFilter,EntryFilter includeFilter))。

可以跟進對應(yīng)版本spring-boot-loader源碼進行調(diào)整。

   public static void main(String args[]) throws Exception {
        String jarPath = "C:\\Users\\root\\Desktop\\make-test.jar";
		// 方案一:spring-boot-loader
        long start1 = System.currentTimeMillis();
        getClassInfoByJarLib(jarPath);
        long end1 = System.currentTimeMillis();
        log.info("收集所有l(wèi)ib類ClassInfo,花費時間={}",(end1-start1));
    } 

    public static void getClassInfoByJarLib(String jarPath) {
        String filePath;
        String separator = File.separator;
        if("\\".equals(separator)){
            // windows系統(tǒng)使用如下路徑
            filePath = "file:/"+ URLDecoder.decode(jarPath, StandardCharsets.UTF_8).replaceAll("\\\\","/")+"!/";
        }else if("/".equals(separator)){
            // linux系統(tǒng)使用如下路徑
            filePath = "file:"+ URLDecoder.decode(jarPath, StandardCharsets.UTF_8).replaceAll("\\\\","/")+"!/";
        }else {
             throw new RuntimeException("未知操作系統(tǒng),解析jarLib失敗");
        } 
        String rootJarPath = "jar:"+ filePath;
        try {
            JarFileArchive jarFileArchive = new JarFileArchive(new Handler().getRootJarFileFromUrl(new URL(rootJarPath)));
            //getNestedArchives獲取嵌套的jar等文件,參數(shù)是個EntryFilter,過濾條件
            jarFileArchive.getNestedArchives(entry -> entry.getName().startsWith("BOOT-INF/lib/") && entry.getName().endsWith(".jar"))
                    .forEach(archive -> {
                        archive.iterator().forEachRemaining(entry -> {
                            String entryName = entry.getName();
                            // 過濾嵌套jar包中字節(jié)碼文件
                            if (entryName.endsWith(".class")) {
                                String className = entryName.replace('/', '.').replace(".class", "");
                                log.info("className:{}",className);
                            }
                        });
                    });
        } catch (IOException e) {
            log.error("解析嵌套jarLib中ClassInfo異常,jarPath={}",jarPath,e);
            throw new RuntimeException(e);
        }
    }

三、JarFile方式

1.demo案例

   public static void main(String args[]) throws Exception {
        String jarPath = "C:\\Users\\root\\Desktop\\make-test.jar";
		// 方案二:JarFile
        long start2 = System.currentTimeMillis();
        processJar(jarPath);
        long end2 = System.currentTimeMillis();
        log.info("收集所有l(wèi)ib類ClassInfo,花費時間={}",(end2-start2));
    } 
    private static void processJar(String jarPath){
        try (JarFile jarFile = new JarFile(new File(jarPath))) {
            jarFile.stream().parallel()
                    // 過濾出所有符合要求的jar包
                    .filter(entry -> !entry.isDirectory() && entry.getName().startsWith("BOOT-INF/lib/") && entry.getName().endsWith(".jar"))
                    .forEach(entry -> processNestedJar(jarFile, entry.getName()));
        } catch (IOException e) {
            log.error("解析嵌套jarLib中ClassInfo異常,jarPath={}",jarPath,e);
            throw new RuntimeException(e);
        }
    }

    private static void processNestedJar(JarFile jarFile, String entryName){
        // 處理嵌套jar文件
        try (InputStream nestedJarStream = jarFile.getInputStream(jarFile.getJarEntry(entryName));
            JarInputStream jarInputStream = new JarInputStream(nestedJarStream)) {
            JarEntry nestedEntry;
            while ((nestedEntry = jarInputStream.getNextJarEntry()) != null) {
                if (nestedEntry.isDirectory()) {
                    continue;
                }
                String nestedEntryName = nestedEntry.getName();
                if (!nestedEntryName.endsWith(".class")) {
                    continue;
                }
                try {
                    String className = nestedEntryName.replace('/', '.').replace(".class", "");
					log.info("className:{}",className);
                } catch (Exception e) {
                    log.error("目標類={}查找失敗",nestedEntryName,e);
					throw new RuntimeException(e);
                }
            }
        } catch (IOException e) {
		    log.error("目標類={}查找失敗",entryName,e);
            throw new RuntimeException(e);
        }
    }

四、兩種方式對比

實測項目make-test.jar中所有依賴lib約200個,其中所有class字節(jié)碼文件約7萬多個。

方案JarFileArchive約1.5s全部解析,方案JarFile約6s全部解析。

總結(jié)

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Java之@TableField注解的用法解析

    Java之@TableField注解的用法解析

    MyBatis-Plus的@TableField注解用于控制實體類字段與數(shù)據(jù)庫表字段的映射關(guān)系,支持字段映射、忽略、插入和更新控制、自定義填充策略和類型轉(zhuǎn)換等
    2025-01-01
  • Java正則驗證電話,手機,郵箱,日期,金額的方法示例

    Java正則驗證電話,手機,郵箱,日期,金額的方法示例

    這篇文章主要介紹了Java正則驗證電話,手機,郵箱,日期,金額的方法,結(jié)合具體實例形式分析了Java針對電話,手機,郵箱,日期,金額的正則判定操作技巧,需要的朋友可以參考下
    2017-03-03
  • Java servlet、filter、listener、interceptor之間的區(qū)別和聯(lián)系

    Java servlet、filter、listener、interceptor之間的區(qū)別和聯(lián)系

    這篇文章主要介紹了Java servlet、filter、listener、interceptor之間的區(qū)別和聯(lián)系的相關(guān)資料,需要的朋友可以參考下
    2016-11-11
  • 詳解Java線程中斷知識點

    詳解Java線程中斷知識點

    在本篇文章中我們給大家分享了關(guān)于Java線程中斷的相關(guān)知識點內(nèi)容以及相關(guān)代碼實例,有興趣的朋友們可以學(xué)習(xí)下。
    2018-09-09
  • Mac M1 Maven安裝與配置教程

    Mac M1 Maven安裝與配置教程

    文章詳細介紹了Maven的安裝配置步驟,包括下載解壓、設(shè)置環(huán)境變量路徑、編輯bash_profile文件,以及修改settings.xml配置本地倉庫和鏡像源,最后通過mvn -v驗證配置是否成功
    2025-09-09
  • Spring中@Validated和@Valid區(qū)別淺析

    Spring中@Validated和@Valid區(qū)別淺析

    @Valid是javax.validation里的,?@Validated是@Valid?的一次封裝,是Spring提供的校驗機制使用,下面這篇文章主要給大家介紹了關(guān)于Spring中@Validated和@Valid區(qū)別的相關(guān)資料,需要的朋友可以參考下
    2022-04-04
  • SpringBoot2線程池定義使用方法解析

    SpringBoot2線程池定義使用方法解析

    這篇文章主要介紹了SpringBoot2線程池定義使用方法解析,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-03-03
  • Java線程組操作實例分析

    Java線程組操作實例分析

    這篇文章主要介紹了Java線程組操作,結(jié)合實例形式分析了ThreadGroup類創(chuàng)建與使用線程組相關(guān)操作技巧,需要的朋友可以參考下
    2019-09-09
  • 深入剖析Java中Map.Entry的方法與實戰(zhàn)應(yīng)用

    深入剖析Java中Map.Entry的方法與實戰(zhàn)應(yīng)用

    在Java集合框架中,Map.Entry扮演著連接鍵值對的橋梁角色,作為Map接口的內(nèi)部接口,它封裝了鍵值對的本質(zhì),是高效處理映射數(shù)據(jù)的核心工具,下面我我們就來深入剖析Map.Entry的概念,方法及實戰(zhàn)應(yīng)用
    2025-06-06
  • JavaWeb文件上傳入門教程

    JavaWeb文件上傳入門教程

    這篇文章主要為大家詳細介紹了JavaWeb文件上傳入門教程,分析了文件上傳原理、介紹了第三方上傳組件,感興趣的小伙伴們可以參考一下
    2016-06-06

最新評論

河西区| 普定县| 河津市| 托克逊县| 阿图什市| 波密县| 鄄城县| 巧家县| 炎陵县| 潼南县| 延边| 南溪县| 泉州市| 广州市| 海门市| 龙胜| 福清市| 句容市| 庆城县| 屏南县| 长沙市| 达日县| 绥化市| 富顺县| 南郑县| 峨山| 虎林市| 灵寿县| 扎囊县| 东方市| 达尔| 德格县| 西昌市| 宁河县| 天长市| 南京市| 沅江市| 山丹县| 乌拉特前旗| 紫阳县| 巨鹿县|