我正在使用EclEmma進行覆蓋率分析。EclEmma爲什麼不包含syncronized(MyClass.class)?
我的Java代碼包含一個同步的(MyClass.class){}塊。
EclEmma說它只是部分覆蓋,事件雖然我有一個單元測試,其中一個線程訪問和另一個線程被阻止。
是否有可能使用EclEmma完全覆蓋同步?
我可以通過某種方式註釋代碼來告訴EclEmma爲此行提供全面覆蓋嗎?
親切的問候 羅傑
我正在使用EclEmma進行覆蓋率分析。EclEmma爲什麼不包含syncronized(MyClass.class)?
我的Java代碼包含一個同步的(MyClass.class){}塊。
EclEmma說它只是部分覆蓋,事件雖然我有一個單元測試,其中一個線程訪問和另一個線程被阻止。
是否有可能使用EclEmma完全覆蓋同步?
我可以通過某種方式註釋代碼來告訴EclEmma爲此行提供全面覆蓋嗎?
親切的問候 羅傑
我不知道這是可能得到一個全覆蓋,因爲issue 2939804報道:
EMMA總是標誌着
synchronized(..)
爲部分覆蓋例子:
synchronized (lock) // partially covered (yellow line in EclEmma)
{
// ...
}
synchronized (this) // partially covered (yellow line in EclEmma)
{
// ...
}
也許一個不同的工具(like Cobertura)會產生不同的結果? (我最近沒有測試過)。
2012更新臘(超過2年後):
將點亮爲綠色,如果同步塊包含一個對象監視器上等待代碼,和測試會中斷等待的線程。
經過一些實驗後,如果塊正常完成並由於異常突然完成,我能夠實現行的完整覆蓋。
我相信問題是MyClass.class
這顯然是利用
http://emma.sourceforge.net/faq.html#q.fractional.examples
隱分支由於隱藏的Class.forName()實現。這種情況是 相當不幸,因爲它很常見,但程序員 幾乎沒有控制它。
因爲Class.forName()可以拋出檢查異常,所以編譯器 會發出一個catch塊,將其重新拋出爲未選中狀態。該捕捉塊 在實踐中很難執行,但它成功地將行 標記爲部分覆蓋。
我錯過了第一次閱讀。
我會嘗試重寫我的代碼以獲得全面覆蓋。
/Roger
EclEmma使用下面的Jacoco進行覆蓋率分析。
正如上文Jacoco的(目前不存在的)JAVAC.SYNC filtering option,該行爲是用於同步的塊中產生的字節代碼的結果是:
一個Java同步塊被編譯成兩個字節碼指令:在所述MONITORENTER在塊的結尾處開始和MONITOREXIT。
爲了確保監視器在任何情況下都被釋放,安裝了一個指向另一個MONITOREXIT指令的異常處理程序。這個異常處理程序塊通常會導致部分行覆蓋,這從源代碼的角度來看是沒有意義的。
一個相關Jacoco issue 245解釋的異常如何被觸發,達到全覆蓋,應該有這樣的需要,同樣通過@森 - 萊恩解釋說:
(Hi Arie)。所以Jacoco並不理解控制流是安全的*:如果你到達了入口點,你將會*到達出口點。我想象一個帶有局部變量的塊被編譯成一個塊,它初始化本地,執行主體並清理本地,並且在塊的周圍包裹一個額外的隱式異常處理程序,以便在發生異常時清理本地。這在風格上看起來完全一樣;但你可以通過「執行」來完全覆蓋一個塊。 (我們的Java測試覆蓋工具可以測試源代碼,不會混淆)。 – 2016-06-01 12:46:49
看起來你是對的。我試過這個:Object synch = MyClass.class; synchronized(synch){}但它沒有幫助,即使我的測試有一個線程正在等待,另一個線程正在獲取互斥體。 – 2010-09-15 08:00:24
根據我的經驗,如果同步塊包含在對象監視器上等待的代碼,並且測試會中斷等待的線程,則'synchronized'將點亮爲綠色。不過,我從來沒有打算深入EMMA的儀器,以確定在一般情況下是否屬實。 – 2012-12-13 23:17:52
經過一些實驗後,如果同步塊正常完成*和*由於異常突然完成,我能夠實現'synchronized'行的完全覆蓋。 – 2012-12-14 00:41:44