在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

引入JaCoCo導致的類型轉換問題分析

京東云 ? 來源:jf_75140285 ? 作者:jf_75140285 ? 2024-08-06 10:30 ? 次閱讀

一、問題描述

JaCoCo是一款被廣泛應用于公司內部的開源覆蓋率工具,將其引用至測試環境后,機器啟動正常,但在操作下單時出現異常,阻塞下單流程。

去除JaCoCo配置、重新編譯和部署后下單功能恢復正常。堆棧信息顯示,問題源于系統對請求字段進行加密時出現異常,因為無法完成類型轉換拋出異常,“[Z cannot be cast to [Ljava.lang.Object”,從而阻塞下單流程。

以下為報錯堆棧信息:

java.lang.ClassCastException: [Z cannot be cast to [Ljava.lang.Object;
	at com.jd.**.TdeProxy.encryptObject(TdeProxy.java:93) 
	at com.jd.**.TdeProxy.encryptObject(TdeProxy.java:133) 
	at com.jd.**.TdeProxy.encryptObject(TdeProxy.java:90) 
	at com.jd.**.TdeProxy.encryptObject(TdeProxy.java:133) 
	at com.jd.**.TdeProxy.encryptObject(TdeProxy.java:90) 
	at com.jd.**.TdeProxy.encryptObject(TdeProxy.java:133) 
	at com.jd.**.TdeProxy.encryptObject(TdeProxy.java:133)
	at com.jd.**.TdeProxy.$$FastClassBySpringCGLIB$$4fa3c52.invoke() 
	at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) 
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:769) 
    ..省略

二、問題分析

1.報錯代碼

定位報錯信息顯示的代碼位置,確認該部分代碼并沒有被修改過。報錯提示指出屬性應為數組類型,但在需要加密的類屬性中并沒有涉及數組類型的處理。那么“[Z”這個類型又是從何而來呢?這種情況下不禁讓人懷疑,在某個時刻類可能被修改過。

報錯信息中的"[Z"代表的是Java中的boolean類型數組。在Java中,基本數據類型的數組也會被表示為類似于"[Z"、"[B"、"[L"等形式的字符串,這可能是因為在程序運行過程中對類進行了動態修改或者反射操作導致的。

以下為報錯處的代碼片段,在將obj轉換為Object[]時出現異常,既然已經識別出是數組,但是又無法完成類型轉換,具體的原因需要進一步分析。

public void encryptObject(Object obj, String type) throws IllegalAccessException {
    /***省略***/
    if (Map.class.isAssignableFrom(clazz)) {
        /***省略***/
    } else if(Iterable.class.isAssignableFrom(clazz)) {
        /***省略***/
    } else if(clazz.isArray()) {
        /**********************報錯代碼行****************/
        for (Object o : (Object[]) obj) {
        /**********************報錯代碼行****************/
            this.encryptObject(o, type);
        }
    } else {
        Boolean encryptFlag = null;
        Field[] fields = this.getDeclaredFieldsAll(clazz);
        for (Field field : fields) {
            /***省略***/
        }
        /***省略***/
        for (Field field : fields) {
            Class fieldClazz = field.getType();
            if (fieldClazz == String.class) {
                /***省略***/
            } else {
                field.setAccessible(true);
                Object fieldValue = field.get(obj);
                this.encryptObject(fieldValue, type);
            }
        }
    }
}

2.分析路徑

閱讀代碼可以看出encryptObject方法是通過遞歸實現的,其主要功能是對有效集合進行遍歷,所以問題的重點不是遞歸的過程,而是推進遞歸過程的元素集合,集合中的元素無法正常進行類型轉換導致報錯,這就需要檢查getDeclaredFieldsAll方法,該方法在運行時返回的集合中可能包含意料之外的元素,以下為具體實現代碼:

public Field[] getDeclaredFieldsAll(Class clazz) {
    List fieldsList = new ArrayList();
    while (clazz != null) {
        Field[] declaredFields = clazz.getDeclaredFields();
        fieldsList.addAll(Arrays.asList(declaredFields));
        clazz = clazz.getSuperclass();
    }
    return fieldsList.toArray(new Field[fieldsList.size()]);
}

由于已確認引入JaCoCo后對類進行了修改,只需觸發任一流程以獲取類的所有屬性,通過設置斷點并觀察集合中的元素,即可查看具體修改情況。

?

?

此時已經可以解釋為什么引入JaCoCo會導致異常。報錯中的類型“[Z”為合成的屬性,引入JaCoCo會給類添加一個名為$jacocoData的bool數組類型屬性,回到報錯代碼位置,出現報錯是因為在識別到一個數組類型時進行了類型轉換,在這里也找到了問題的答案。

涉及到合成屬性/方法和JaCoCo的實現原理,下面進行簡單的介紹。

3.追本溯源

(1)合成屬性和方法

合成屬性/方法是由Java編譯器在編譯過程中自動生成,并不是研發顯示編寫的,而是為了支持編譯器內部的實現細節而生成的,下面針對合成方法進行一個舉例說明。

public class Pack {
    public static void main(String[] args) {
        Pack.Goods goods = new Pack.Goods();
        System.out.println(goods.name);
    }
    private static class Goods {  
       private String name = "手機";
    }
}

將上面的代碼編譯一下,可以看到有三個文件,Pack$Goods.class、Pack.class、Pack$1.class,前兩個一個是內部類,一個是外部類,但是最后一個類并沒有被定義過,接下來分別將內部類和外部類進行反編譯:

import com.jd.ryan.test.Pack.1;
class Pack$Goods {
    private String name; 
    private Pack$Goods() {
        this.name = "手機";
    }
    Pack$Goods(1 x0) {
        this(); 
    }
    static String access$100(Pack$Goods x0) {
        return x0.name; 
    }
}

內部類被反編譯后,可以發現access$100的方法并沒有被定義,但是分析來看name是內部類Goods的私有屬性,但是外部類可以直接引用這個屬性,從語法結構上講這是被允許的,這就需要編譯器在編譯過程處理這種操作,在編譯器看來,外部類和內部類是兩個獨立的類,如果外部類想要訪問內部類的私有屬性,其實是與封裝原則相悖的。那接著看外部類的反編譯結果:

public class com.jd.ryan.test.Pack {
    public com.jd.ryan.test.Pack(); 
        Code:
            0: aload_0
            1: invokespecial #1 //Method java/lang/Object."":()V
    public static void main(java.lang.String[]);
        Code:
            0: new #2           //class com/jd/ryan/test/Pack$Goods
            3: dup
            4: aconst_null
            5: invokespecial #3 //Method com/jd/ryan/test/Pack$Goods."":(Lcom/jd/ryan/test/Pack$1;V
            8: astore_1
            9: getstatic #4     //Field java/lang/System.out:Ljava/io/Printstream;
            12: aload_1
            13: invokestatic #5 //Method com/jd/ryan/test/Pack$Goods.access$100:(Lcom/jd/ryan/test/Pack$Goods.access$100:(Lcom/jd/ryan/test/Pack$Goods;)Ljava/lang/String;
            16: invokevirtual #6//Method java/io/PrintStream.println:(Ljava/lang/String;)V
            19: return
}

在代碼實現中外部類直接打印內部類的name屬性值,來看這行指令:

“Method com/jd/ryan/test/Pack$Goods.access$100:(Lcom/jd/ryan/test/Pack$Goods.access$100:(Lcom/jd/ryan/test/Pack$Goods;)Ljava/lang/String;”

從字節碼中表明是通過調用了內部類的access$100方法,這個方法是一個靜態方法,它可以返回內部類的name屬性,是Goods的私有屬性,所以access$100就是編譯器用來做內部訪問生成的一個合成方法。

編譯器可以通過生成合成屬性和方法來實現一些內部優化或者內部實現,所以在使用反射機制實現一些工具時,在運行時拿到的類屬性信息還可能會有一些未知的屬性或者方法,這就需要工具類的代碼具備一定的健壯性,對獲取到的類屬性進行類型轉換時應該考慮到非業務字段的情況,并且能夠對運行時異常進行捕獲,讓工具聚焦在可以處理的范圍,不能影響正常的業務流程。

(2)JaCoCo原理簡述

JaCoCo利用ASM在字節碼中插入探針指針(Probe指針),每個探針都是一個布爾變量(true表示執行,false表示未執行)。程序運行時通過修改這些指針來檢測代碼的執行情況,而不會改變原始代碼的行為。提到的$jacocoData數組用于保存這些執行結果,JaCoCo根據控制流類型采用不同的探針插入策略,這些探針不會改變方法的行為,只是記錄它們已經執行的事實。

本文不再深入介紹JaCoCo的工作原理,感興趣的同學可以查閱資料。

三、解決辦法

通過問題分析已經確定是$jacocoData導致的,那就需要在獲取屬性集合的的時對這類屬性進行過濾,實現方法通過isSynthetic()方法區分field屬性類型,isSynthetic是Java中的一個修飾符,用于標記一個類、方法或字段是否由編譯器生成。

List fieldsList = Arrays.stream(declaredFields)
                               .filter(field -> !field.isSynthetic())
                               .collect(Collectors.toList());

代碼修改后,測試環境添加JaCoCo相關配置,編譯部署發布后可正常下單,從斷點信息來看,$jacocoData已經被過濾掉了。


審核編輯 黃宇

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 測試
    +關注

    關注

    8

    文章

    5384

    瀏覽量

    127083
  • 開源
    +關注

    關注

    3

    文章

    3408

    瀏覽量

    42719
  • 編譯
    +關注

    關注

    0

    文章

    661

    瀏覽量

    33050
收藏 人收藏

    評論

    相關推薦

    【電磁兼容技術案例分享】LVDS信號因經連接器轉接導致RS問題整改分析案例

    【電磁兼容技術案例分享】LVDS信號因經連接器轉接導致RS問題整改分析案例
    的頭像 發表于 12-12 12:01 ?220次閱讀
    【電磁兼容技術案例分享】LVDS信號因經連接器轉接<b class='flag-5'>導致</b>RS問題整改<b class='flag-5'>分析</b>案例

    不同類型ACDC轉換器優缺點 ACDC轉換器負載能力分析

    ACDC轉換器是將交流電(AC)轉換為直流電(DC)的設備,在電力電子領域具有廣泛的應用。以下是不同類型ACDC轉換器的優缺點以及ACDC轉換
    的頭像 發表于 12-09 10:53 ?652次閱讀

    不同類型adc的優缺點分析

    ADC(模數轉換器)是將模擬信號轉換為數字信號的電路,根據轉換原理和應用需求的不同,ADC可以分為多種類型,每種類型都有其獨特的優缺點,以下
    的頭像 發表于 11-19 16:58 ?1246次閱讀

    不同類型AD轉換器的比較

    在電子系統中,模數轉換器(Analog-to-Digital Converter,簡稱ADC或A/D轉換器)是至關重要的一環,它負責將連續的模擬信號轉換為離散的數字信號,以便于數字系統進行處理和
    的頭像 發表于 10-05 11:36 ?2414次閱讀

    【電磁兼容技術案例分享】因喚醒線導致的CE電壓法測試超標整改分析案例

    【電磁兼容技術案例分享】因喚醒線導致的CE電壓法測試超標整改分析案例
    的頭像 發表于 09-28 08:03 ?476次閱讀
    【電磁兼容技術案例分享】因喚醒線<b class='flag-5'>導致</b>的CE電壓法測試超標整改<b class='flag-5'>分析</b>案例

    靜態轉換開關類型有哪些

    轉換開關
    深圳市寶威特電源有限公司
    發布于 :2024年07月24日 14:38:14

    DCAC電源模塊在不同的電源類型之間進行轉換

    BOSHIDA DC/AC電源模塊在不同的電源類型之間進行轉換 電力轉換是現代社會不可或缺的一部分,它使我們能夠在不同的電源類型之間進行轉換
    的頭像 發表于 07-05 14:42 ?580次閱讀
    DCAC電源模塊在不同的電源<b class='flag-5'>類型</b>之間進行<b class='flag-5'>轉換</b>

    CAN不通訊導致CE電流法測試超標整改分析案例

    CAN不通訊導致CE電流法測試超標整改分析案例
    的頭像 發表于 07-05 08:17 ?935次閱讀
    CAN不通訊<b class='flag-5'>導致</b>CE電流法測試超標整改<b class='flag-5'>分析</b>案例

    反激式轉換器的工作原理和主要類型

    在電子技術的快速發展中,電源轉換器作為電子設備的重要組成部分,其性能直接影響到整個系統的穩定性和可靠性。反激式轉換器,作為電源轉換器的一種,因其獨特的結構和工作原理,在電源領域得到了廣泛的應用。本文將詳細闡述反激式
    的頭像 發表于 05-23 17:10 ?850次閱讀

    AC-AC轉換器的工作原理與主要類型

    AC-AC轉換器,即交流-交流轉換器,是一種將一種交流電轉換為另一種交流電的電子設備。在現代電子系統中,AC-AC轉換器扮演著至關重要的角色,它們被廣泛應用于電力電子、工業自動化、通信
    的頭像 發表于 05-23 17:09 ?6474次閱讀

    逆變器的常見類型及其特點分析

    逆變器,作為電力電子領域的重要設備,其功能是將直流電(DC)轉換為交流電(AC)。隨著電力電子技術的不斷發展,逆變器的類型也日益多樣化,以滿足不同領域和場景的需求。本文將對逆變器的常見類型進行詳細
    的頭像 發表于 05-21 16:29 ?1830次閱讀

    電源轉換器的類型及其特點

    電源轉換器,作為電子設備中不可或缺的一部分,其重要性不言而喻。無論是在日常生活中,還是在工業生產中,電源轉換器都發揮著至關重要的作用。本文將詳細介紹電源轉換器的類型及其特點,旨在幫助讀
    的頭像 發表于 05-21 15:22 ?1023次閱讀

    C語言如何掌握強制類型轉換的精髓

    強制類型轉換是把變量從一種類型轉換為另一種數據類型。例如,如果您想存儲一個 long 類型的值到
    的頭像 發表于 02-26 11:00 ?569次閱讀
    C語言如何掌握強制<b class='flag-5'>類型</b><b class='flag-5'>轉換</b>的精髓

    arcgis值類型與字段類型不兼容

    ArcGIS是一個地理信息系統軟件,可以用來處理、分析和可視化地理數據。在ArcGIS中,值類型和字段類型之間需要相互匹配,否則會導致不兼容的錯誤。 在ArcGIS中,值
    的頭像 發表于 02-25 11:14 ?1872次閱讀

    頻譜分析類型和技術工作原理

    與任何測試設備一樣,可以找到幾種類型的頻譜分析儀。各種類型分析儀以不同的方式運行,盡管它們的目的相同:分析頻譜,查看信號。
    發表于 02-08 09:52 ?409次閱讀
    頻譜<b class='flag-5'>分析</b>儀<b class='flag-5'>類型</b>和技術工作原理
    主站蜘蛛池模板: 5g成人影院 | 天堂网色 | 一级做a爰片久久毛片免费 一级做a爰片久久毛片免费看 | 人人骚 | 五月天婷婷网站 | 成人欧美一区二区三区黑人免费 | 日韩精品网址 | 免费观看一级一片 | 38pao强力打造永久免费高清视频 | 免费簧片视频 | 国产精品莉莉欧美自在线线 | 欧美日剧在线免费 | 天天色天天干天天射 | 色爽女视频 | 婷婷丁香激情 | 日韩天堂在线观看 | 天天干夜夜怕 | 中文字幕一区二区三区 精品 | 国内a级毛片免费··· | 四虎新地址4hu 你懂的 | 黄色亚洲 | 四虎国产永久在线精品免费观看 | 欧美中出 | 国产色视频在线 | 国内一级毛片 | 四虎国产永久在线观看 | abc欧美成人影院 | 久久99国产精品久久99 | 丁香视频在线 | 婷婷激情电影 | 成 人色 网 站999 | 久久精品国产清自在天天线 | 色综合色综合色综合网址 | 天堂网a| 免费一级毛片私人影院a行 免费一级毛片无毒不卡 | 中文天堂最新版在线中文 | 亚洲免费影视 | 你懂得在线网址 | 一二三区在线视频 | 免费黄色一级 | 7777奇米影视 |