91欧美超碰AV自拍|国产成年人性爱视频免费看|亚洲 日韩 欧美一厂二区入|人人看人人爽人人操aV|丝袜美腿视频一区二区在线看|人人操人人爽人人爱|婷婷五月天超碰|97色色欧美亚州A√|另类A√无码精品一级av|欧美特级日韩特级

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

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

3天內(nèi)不再提示

引入JaCoCo導(dǎo)致的類型轉(zhuǎn)換問題分析

京東云 ? 來源:jf_75140285 ? 作者:jf_75140285 ? 2024-08-06 10:30 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

一、問題描述

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

去除JaCoCo配置、重新編譯和部署后下單功能恢復(fù)正常。堆棧信息顯示,問題源于系統(tǒng)對請求字段進行加密時出現(xiàn)異常,因為無法完成類型轉(zhuǎn)換拋出異常,“[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.報錯代碼

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

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

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

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方法是通過遞歸實現(xiàn)的,其主要功能是對有效集合進行遍歷,所以問題的重點不是遞歸的過程,而是推進遞歸過程的元素集合,集合中的元素?zé)o法正常進行類型轉(zhuǎn)換導(dǎo)致報錯,這就需要檢查getDeclaredFieldsAll方法,該方法在運行時返回的集合中可能包含意料之外的元素,以下為具體實現(xiàn)代碼:

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后對類進行了修改,只需觸發(fā)任一流程以獲取類的所有屬性,通過設(shè)置斷點并觀察集合中的元素,即可查看具體修改情況。

?

?

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

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

3.追本溯源

(1)合成屬性和方法

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

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,前兩個一個是內(nèi)部類,一個是外部類,但是最后一個類并沒有被定義過,接下來分別將內(nèi)部類和外部類進行反編譯:

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; 
    }
}

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

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
}

在代碼實現(xiàn)中外部類直接打印內(nèi)部類的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;”

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

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

(2)JaCoCo原理簡述

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

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

三、解決辦法

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

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

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


審核編輯 黃宇

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 測試
    +關(guān)注

    關(guān)注

    9

    文章

    6267

    瀏覽量

    131479
  • 開源
    +關(guān)注

    關(guān)注

    3

    文章

    4244

    瀏覽量

    46267
  • 編譯
    +關(guān)注

    關(guān)注

    0

    文章

    694

    瀏覽量

    35222
收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關(guān)推薦
    熱點推薦

    嵌入式中的浮點型數(shù)據(jù)轉(zhuǎn)換為字節(jié)類型的三種方法

    MCU的存儲模塊中去。所以說要保存一個浮點型數(shù)據(jù)到MCU前需要先把浮點型數(shù)據(jù)轉(zhuǎn)換成字節(jié)的形式。下面就來說一說浮點型轉(zhuǎn)換為字節(jié)類型的一些方法: 方法一 強制轉(zhuǎn)換,就是把浮點型數(shù)據(jù)直接賦
    發(fā)表于 01-07 06:28

    枚舉類型的講解

    green, 3. blue): 3 你喜歡的顏色是藍色 也可以把整數(shù)轉(zhuǎn)換為枚舉類型: //Example 07 #include #include int main() { enum
    發(fā)表于 12-08 08:14

    C語言自動類型轉(zhuǎn)換

    一、自動類型轉(zhuǎn)換 數(shù)據(jù)類型存在自動轉(zhuǎn)換的情況. 自動轉(zhuǎn)換發(fā)生在不同數(shù)據(jù)類型運算時,在編譯的時候
    發(fā)表于 11-25 08:04

    C語言強制類型轉(zhuǎn)換

    強制類型轉(zhuǎn)換是通過定義類型轉(zhuǎn)換運算來實現(xiàn)的。其一般形式為: (數(shù)據(jù)類型) (表達式) 其作用是把表達式的運算結(jié)果強制
    發(fā)表于 11-24 06:32

    模數(shù)轉(zhuǎn)換器主要類型有哪些

    模數(shù)轉(zhuǎn)換器采用逐步比較逼近策略,通過二進制搜索算法將模擬信號轉(zhuǎn)換為數(shù)字值。這類轉(zhuǎn)換器在轉(zhuǎn)換速度和精度之間實現(xiàn)了良好平衡,廣泛應(yīng)用于中等采樣速率和中等精度的場景,如工業(yè)控制系統(tǒng)和醫(yī)療儀器
    的頭像 發(fā)表于 11-03 16:36 ?712次閱讀

    vivado時序分析相關(guān)經(jīng)驗

    vivado綜合后時序為例主要是有兩種原因導(dǎo)致: 1,太多的邏輯級 2,太高的扇出 分析時序違例的具體位置以及原因可以使用一些tcl命令方便快速得到路徑信息
    發(fā)表于 10-30 06:58

    PPKTP晶體在波長轉(zhuǎn)換中的特性分析與應(yīng)用選擇

    波長轉(zhuǎn)換技術(shù)在激光系統(tǒng)、量子光學(xué)和光譜分析等領(lǐng)域具有重要作用,其核心是通過非線性光學(xué)效應(yīng)實現(xiàn)高效、靈活的波段調(diào)諧。在眾多非線性晶體中,周期極化磷酸氧鈦鉀(PPKTP)以其高損傷閾值和可見波段的低光
    的頭像 發(fā)表于 09-29 17:36 ?922次閱讀
    PPKTP晶體在波長<b class='flag-5'>轉(zhuǎn)換</b>中的特性<b class='flag-5'>分析</b>與應(yīng)用選擇

    工業(yè)相機的類型及不同類型的應(yīng)用

    工業(yè)相機根據(jù)不同的分類標(biāo)準,可分為多種類型,每種類型都有其獨特的應(yīng)用場景。
    的頭像 發(fā)表于 08-29 17:07 ?851次閱讀
    工業(yè)相機的<b class='flag-5'>類型</b>及不同<b class='flag-5'>類型</b>的應(yīng)用

    【電磁兼容技術(shù)案例分享】TVS選型導(dǎo)致浪涌問題整改分析案例

    【電磁兼容技術(shù)案例分享】TVS選型導(dǎo)致浪涌問題整改分析案例
    的頭像 發(fā)表于 06-11 17:29 ?749次閱讀
    【電磁兼容技術(shù)案例分享】TVS選型<b class='flag-5'>導(dǎo)致</b>浪涌問題整改<b class='flag-5'>分析</b>案例

    光纖頭可以直接轉(zhuǎn)換網(wǎng)線頭嗎

    光纖頭不能直接轉(zhuǎn)換網(wǎng)線頭,需要通過光電轉(zhuǎn)換設(shè)備(如光纖收發(fā)器或光電交換機)將光信號轉(zhuǎn)換為網(wǎng)絡(luò)信號,才能與網(wǎng)線連接。以下是具體分析: 一、光纖與網(wǎng)線的傳輸特性差異 信號
    的頭像 發(fā)表于 06-03 10:27 ?3161次閱讀

    VirtualLab:光柵的優(yōu)化與分析

    的算法: TEA和FMM(也稱為RCWA)。比較了不同周期的兩種類型的光柵(正弦和閃耀)結(jié)果。 傾斜光柵的參數(shù)優(yōu)化及公差分析 以傅里葉模態(tài)法(FMM)作為參數(shù)優(yōu)化的核心,設(shè)計了一個傾斜光柵來實現(xiàn)高衍射效率將光耦合到光波導(dǎo)中的目的。此外,還
    發(fā)表于 05-23 08:49

    【電磁兼容技術(shù)案例分享】因視頻光電轉(zhuǎn)換導(dǎo)致的BCI問題案例

    【電磁兼容技術(shù)案例分享】因視頻光電轉(zhuǎn)換導(dǎo)致的BCI問題案例
    的頭像 發(fā)表于 05-14 18:11 ?435次閱讀
    【電磁兼容技術(shù)案例分享】因視頻光電<b class='flag-5'>轉(zhuǎn)換</b>器<b class='flag-5'>導(dǎo)致</b>的BCI問題案例

    如何操作時域網(wǎng)絡(luò)分析儀進行故障檢測?

    操作時域網(wǎng)絡(luò)分析儀(TDNA)進行故障檢測需結(jié)合儀器設(shè)置、校準、時域轉(zhuǎn)換及數(shù)據(jù)分析等步驟。以下為系統(tǒng)化操作指南,涵蓋關(guān)鍵流程、參數(shù)配置及典型案例:一、操作前準備1. 儀器連接與配置 硬件連接
    發(fā)表于 04-30 14:15

    LTspice里壓敏電阻MOV怎么引入?

    LTspice里壓敏電阻MOV怎么引入
    發(fā)表于 04-28 08:26

    國產(chǎn)模數(shù)轉(zhuǎn)換器100%替換ADS1278應(yīng)用于振動和模態(tài)分析

    國產(chǎn)模數(shù)轉(zhuǎn)換器100%替換ADS1278應(yīng)用于振動和模態(tài)分析
    的頭像 發(fā)表于 04-16 09:50 ?1028次閱讀
    國產(chǎn)模數(shù)<b class='flag-5'>轉(zhuǎn)換</b>器100%替換ADS1278應(yīng)用于振動和模態(tài)<b class='flag-5'>分析</b>