为什么 EclEmma 不覆盖 synchronized(MyClass.class)?

发布于 2024-09-19 07:40:59 字数 232 浏览 10 评论 0原文

我正在使用 EclEmma 进行覆盖率分析。

我的Java代码包含一个synchronized(MyClass.class) {}块。

EclEmma 说它只被部分覆盖,尽管我有一个单元测试,其中一个线程获得访问权限而另一个线程被阻止。

是否可以使用 EclEmma 全面覆盖同步?

我可以以某种方式注释代码来告诉 EclEmma 完全覆盖这一行吗?

亲切的问候 罗杰

I'm using EclEmma for coverage analysis.

My Java code includes a synchronized(MyClass.class) {} block.

EclEmma says it is only partially covered, event though I've got a unit test in which one thread gets access and another thread is blocked.

Is it possible to get full coverage of synchronized using EclEmma?

Can I annotate the code in some way to tell EclEmma to give this line full coverage?

Kind regards
Roger

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

七七 2024-09-26 07:40:59

我不确定是否可以获得完整的覆盖,因为 问题 2939804 报告:

EMMA 始终将 synchronized(..) 标记为部分覆盖

示例:

synchronized (lock) // partially covered (yellow line in EclEmma)
{
// ...
}
synchronized (this) // partially covered (yellow line in EclEmma)
{
// ...
}

也许是一个不同的工具 (像 Cobertura) 会产生不同的结果吗? (我最近没有测试过)。


2012 年 12 月更新(两年多后):

Nathan D Ryan 报告

如果同步块包含在对象监视器上等待的代码,并且测试中断了等待线程,

synchronized 将亮为绿色。

经过一些实验,如果 synchronized 块正常完成并由于异常突然完成,我就能够完全覆盖 synchronized 行。

I am not sure it is possible to get a full coverage, since issue 2939804 reports:

EMMA always marks synchronized(..) as partially covered

Examples:

synchronized (lock) // partially covered (yellow line in EclEmma)
{
// ...
}
synchronized (this) // partially covered (yellow line in EclEmma)
{
// ...
}

Maybe a different tool (like Cobertura) would yield a different result? (I have not tested it recently).


Update December 2012 (more than 2 years later):

Nathan D Ryan reports:

synchronized will light to green if the synchronized block contains code that waits on an object monitor, and a test interrupts the waiting thread.

After a little experimentation, I was able to achieve complete coverage of the synchronized line if the synchronized block completed normally and completed abruptly due to an exception.

一人独醉 2024-09-26 07:40:59

EclEmma 在下面使用 Jacoco 进行覆盖率分析。

正如 Jacoco 的(当前不存在)JAVAC.SYNC 过滤选项,该行为是为同步块生成的字节代码的结果:

Java 同步块被编译为两个字节码指令:块开头的 MONITORENTER 和块末尾的 MONITOREXIT。

为了确保在任何情况下都能释放监视器,安装了指向另一个 MONITOREXIT 指令的异常处理程序。此异常处理程序块通常会导致部分行覆盖,从源代码的角度来看,这没有意义。

相关的 Jacoco 问题 245 解释了如何触发异常以达到完全覆盖,如果正如 @nathan-ryan 所解释的:

  1. 一个测试正常执行同步块,
  2. 第二个测试从同步块内抛出(并因此期望)异常。

EclEmma uses Jacoco underneath for the coverage analysis.

As explained in Jacoco's (currently non-existing) JAVAC.SYNC filtering option, the behavior is a result of the byte code generated for synchronized blocks:

A Java synchronized block gets compiled into two bytecode instructions: MONITORENTER at the beginning and MONITOREXIT at the end of the block.

To ensure that the the monitor is released in any case an exception handler is installed which points to another MONITOREXIT instruction. This exception handler block typically causes partial line coverage which doesn't make sense from the source code point of view.

A related Jacoco issue 245 explains how exceptions can be triggered to reach full coverage, should this be desired, as also explained by @nathan-ryan:

  1. One test that executes the synchronized block normally
  2. A second test that throws (and hence expects) an exception from within the synchronized block.
耀眼的星火 2024-09-26 07:40:59

我相信问题是 MyClass.class ,它显然是使用

http://emma.sourceforge.net/faq.html#q.fractional.examples

由于隐藏的 Class.forName() 导致的隐式分支。这个案例是
相当不幸,因为它很常见,但程序员
几乎无法控制它。

因为 Class.forName() 可以抛出检查异常,所以编译器
发出一个 catch 块,将它们重新抛出为未检查的。这个捕获块
在实践中几乎没有执行过,但它成功地划定了界限
部分覆盖。

我在第一次通读时错过了这一点。

我将尝试重写我的代码以获得完整的覆盖范围。

/罗杰

I believe the problem is MyClass.class which apparently is implemented using

http://emma.sourceforge.net/faq.html#q.fractional.examples

Implicit branches due to a hidden Class.forName(). This case is
rather unfortunate because it is pretty common and yet the programmer
has almost no control over it.

Because Class.forName() can throw checked exceptions, the compiler
emits a catch block that rethrows them as unchecked. This catch block
hardly ever executes in practice, but it succeeds in marking the line
as partially covered.

I missed that on the first read-through.

I will try to re-write my code to get full coverage.

/Roger

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文