DEV Community

toydev
toydev

Posted on

Eclipse WTP: JaCoCo Coverage Not Recognized When Running Tomcat in Debug Mode

Introduction

While using Eclipse WTP to run a dynamic web application on Tomcat, I encountered an issue where JaCoCo coverage results depended on how the server was launched.

Specifically, coverage was collected correctly when Tomcat was started with Run, but not when started with Debug.

This article documents the investigation, the findings, and the practical conclusion drawn from them. The goal is not only to fix the issue, but also to clarify why collecting coverage in Debug mode is inherently fragile in this environment.


Preconditions

  • A dynamic web application is launched on Tomcat using Eclipse WTP
  • Tomcat is started from Eclipse using Run As or Debug As
  • JaCoCo is attached manually via JVM options (EclEmma coverage launch is not available for WTP servers)
  • Execution data is imported into Eclipse Coverage view or processed via JaCoCo Ant tasks

JaCoCo agent configuration

Example VM argument used for Tomcat startup:

-javaagent:${project_loc:PROJECT_NAME}/lib/jacoco/jacocoagent.jar=destfile=${project_loc:PROJECT_NAME}/target/jacoco/jacoco.exec,append=false
Enter fullscreen mode Exit fullscreen mode

Environment

  • Windows 11
  • Eclipse (as of 2025-12-12)
    • Eclipse IDE for Enterprise Java and Web Developers 2025-12 (4.38.0)
    • Tomcat 10 (Java 21)

Observed behavior

Coverage recognition differs depending on how Tomcat is launched:

  • Run As → Run on Server

    • JaCoCo coverage is recognized correctly
  • Debug As → Debug on Server

    • JaCoCo coverage is not recognized

Investigation 1: Class file comparison

To determine whether this was a WTP-specific issue, the same JaCoCo setup was tested with a normal Java application:

  • In a non-WTP Java application, coverage works correctly in both Run and Debug modes

Next, the actual class files used by WTP were compared.

  • Compared class files under:
.metadata/.plugins/org.eclipse.wst.server.core/tmp*/wtpwebapps/<project>/WEB-INF/classes
Enter fullscreen mode Exit fullscreen mode

Results:

  • Class files are identical between Run and Debug
  • No timestamp differences

To investigate further, JaCoCo's classdumpdir option was used and dumped classes were analyzed with javap -v.

Finding

  • In Debug mode, class files contain SourceDebugExtension (SMAP)
  • In Run mode, SMAP is not present

Interpretation

This strongly suggests that, when launching a WTP server in Debug mode, class files are modified by Eclipse (or related tooling) before or around class loading, independently of JaCoCo instrumentation.

JaCoCo assumes that:

  • The class definition at execution time
  • And the class definition used for analysis

are structurally identical.

The presence of SMAP breaks this assumption.


Investigation 2: Eclipse configuration

Based on the hypothesis above, Eclipse debug-related settings were reviewed.

The issue disappears when the following setting is disabled:

Preferences → Java → Debug → Use advanced source lookup (JRE 1.5 and higher)
Enter fullscreen mode Exit fullscreen mode

After disabling this option:

  • Coverage is recognized correctly even in Debug mode
  • Java source debugging still works
  • JSP debugging still works

Notes on SMAP (JSR-045)

  • SMAP (Source Map) is defined by JSR-045
  • It is primarily used to map generated code (e.g. JSP) back to original source
  • In Tomcat, SMAP generation for JSPs is handled by JspServlet and enabled by default

    • It can be disabled via suppressSmap

Based on observed behavior:

  • SMAP for Java-originated classes appears to be influenced by Eclipse debug configuration
  • SMAP for JSP-originated classes is handled by Tomcat

Conclusion

Disabling "Use advanced source lookup" is a possible workaround.

However, the broader conclusion is more important:

JaCoCo relies on class definition consistency between execution and analysis.

Debug configurations in IDEs may introduce implicit bytecode modifications (such as SMAP) that violate this assumption.

Therefore:

Collect JaCoCo coverage using Run mode, and reserve Debug mode strictly for investigation and diagnosis.

Trying to collect coverage in Debug mode should generally be avoided in Eclipse WTP environments.


Final remark

This article intentionally focuses on why the issue occurs, rather than treating it as a configuration glitch.

The same problem is likely to reappear in future environments if the underlying assumptions are forgotten.

Writing this down is primarily for my future self — but if it helps someone else avoid the same trap, even better.

Top comments (0)