jacoco底层原理解析
閱讀本文前,建議先了解以下相關知識:
Jacoco使用插樁的方式來記錄覆蓋率數據,是通過一個probe探針來注入。
一、覆蓋率分析機制
有幾種不同的方法來收集覆蓋率信息。對于每種方法,由不同的實現技術,黃色路徑是jacoco推薦的方式,即通過字節碼插樁實現代碼覆蓋率的統計:
?
在ByteCode字節碼上插樁模式有兩種:
1. on-the-fly模式
JVM通過 -javaagent參數指定jar文件啟動代理程序,代理程序在ClassLoader裝載一個class前判斷是否修改class文件,并將探針插入class文件,探針不改變原有方法的行為,只是記錄是否已經執行。
2. offline模式
在測試之前先對文件進行插樁,生成插過樁的class或jar包,測試插過樁的class和jar包,生成覆蓋率信息到文件,最后統一處理,生成報告。
二、jacoco插樁策略
參考文章:Java方法的控制流分析
1、Java字節碼的控制流程圖
要實現對代碼的覆蓋率統計,首先要了解方法的內部控制流。以下面這段java代碼為例
public static void example() {a();if (cond()) {b();} else {c();}d(); }編譯之后的字節碼如下(.class文件中保存的就是字節碼):
public static example()VINVOKESTATIC a()VINVOKESTATIC cond()ZIFEQ L1INVOKESTATIC b()VGOTO L2L1: INVOKESTATIC c()VL2: INVOKESTATIC d()VRETURN控制流通過有條件或無條件操作碼之類的跳轉指令?來實現。跳轉目標在技術上是相對于目標指令的相對偏移。為了提高可讀性,我們改用符號標簽(ASM API也使用此類符號標簽,IFEQ?L1?GOTO?L2):
上面字節碼的控制流程可以用流程圖表示。節點是字節碼指令,邊表示指令之間的控制流。該示例的控制流顯示在該圖的左框中:
2、探針插入策略
探針就是可以插入現有指令之間的一段其他指令,它們不會改變方法的行為,但是會記錄它們已被執行的事實。
jacoco插樁并不是每行,探針實現本身需要多個字節碼指令,因此這將使類文件的大小增加數倍,并顯著降低所檢測類的執行速度。實際上,根據方法的控制流程,每個方法僅需要幾個探針,具體策略如下:
- 在每個方法出口處(返回或拋出)插入探針
- 具有多條指向邊的目標指令的多條指向邊上
二、jacoco原理
Jacoco on-the-fly 模式通過jacoco agent在類加載時對原始類進行插樁,得到插樁后的類。正常class文件加載流程如下:
被jacoco代理的class文件加載流程
?
?
?
?
?
?
總結
以上是生活随笔為你收集整理的jacoco底层原理解析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Chrome DevTools — Ne
- 下一篇: Web开发学习路线图