はじめに
Eclipse WTP を用いて Tomcat 上で動的 Web アプリケーションを実行し、JaCoCo によるカバレッジ計測を行っていたところ、実行方法によってカバレッジの認識結果が変わるという事象に遭遇しました。
具体的には、Tomcat を Run で起動した場合はカバレッジが取得できるのに、Debug で起動すると取得できない という挙動です。
本記事では、この事象について
- どのような挙動が発生したのか
- 何を調査し、何が分かったのか
- 実務上どのように扱うのが妥当か
を整理してまとめます。
発生事象
Tomcat の起動方法によって、JaCoCo のカバレッジ認識結果が以下のように異なりました。
-
「実行(Run)」で Tomcat を起動し実行データを取得
- カバレッジは正常に認識される
-
「デバッグ(Debug)」で Tomcat を起動し実行データを取得
- カバレッジが認識されない
前提
-
Eclipse WTP のサーバ機能を用いて Tomcat に動的 Web アプリケーションを追加して起動する
-
サーバの起動構成(Run / Debug Configuration)の VM 引数に
-javaagentを指定して JaCoCo を有効化する- WTP サーバ起動では EclEmma のカバレッジ実行が利用できないため、手動設定で対応
-
取得した実行データを Eclipse のカバレッジビューにインポート、または JaCoCo の Ant 統合でレポート生成を行う
JaCoCo エージェント設定
Tomcat 起動時に指定していた VM 引数は以下の通りです。
-javaagent:${project_loc:プロジェクト名}/lib/jacoco/jacocoagent.jar=destfile=${project_loc:プロジェクト名}/target/jacoco/jacoco.exec,append=false
環境
- Windows 11
- Eclipse(2025/12/12 時点)
- Eclipse IDE for Enterprise Java and Web Developers 2025-12 (4.38.0)
- Tomcat 10(Java 21)
- Pleiades 2025-09 Java
- Tomcat 11 (Java 25)
- Eclipse IDE for Enterprise Java and Web Developers 2025-12 (4.38.0)
調査 1:クラスファイルの差異調査
まず、WTP 固有の問題かどうかを切り分けるため、通常の Java アプリケーション(非 WTP)に対して同様の JaCoCo 設定を試しました。
- 通常の Java アプリケーションでは、実行・デバッグいずれの場合もカバレッジは正常に取得可能
次に、WTP 環境で使用されるクラスファイル自体に差異があるかを確認しました。
- 以下のディレクトリ配下のクラスファイルを、実行時・デバッグ時で比較
.metadata/.plugins/org.eclipse.wst.server.core/tmp*/wtpwebapps/<プロジェクト名>/WEB-INF/classes
結果は以下の通りです。
- クラスファイルは一致
- タイムスタンプの差異もなし
さらに、JaCoCo エージェントの classdumpdir オプションを利用し、実行時・デバッグ時にロードされたクラスファイルをダンプして javap -v で比較しました。
判明した点
- デバッグ実行時のクラスファイルに SourceDebugExtension(SMAP)が付与されている
- 実行(Run)時のクラスファイルには SMAP が存在しない
なぜこの問題が起きるのか
上記の結果から、Eclipse WTP のサーバ起動(デバッグ構成)では、JaCoCo によるエージェント処理とは別の主体によってクラスファイルに追加情報が付与されている可能性が高いと考えられます。
具体的には、デバッグ実行時に付与される SMAP(SourceDebugExtension) が、JaCoCo の前提条件と衝突していると推測されます。
JaCoCo は、
- 実行時にロードされたクラス定義
- 解析時に使用するクラス定義
が 構造的に一致していること を前提にカバレッジを算出します。
そのため、IDE のデバッグ機能によってクラスファイルに追加情報が付与されると、カバレッジとソースコードの対応付けが正しく行えなくなります。
調査 2:Eclipse の設定
上記の仮説をもとに Eclipse の設定を調査したところ、以下の設定を無効化すると、デバッグ実行時でもカバレッジが正常に取得できることを確認しました。
設定 → Java → デバッグ → 高度なソース・ルックアップを使用する(JRE 1.5 以上)
この設定を無効化した状態では、
- デバッグ実行時でも JaCoCo のカバレッジが認識される
- Java ソースのデバッグは引き続き可能
- JSP のデバッグも問題なく動作
することを確認しています。
SMAP(JSR-045)について
補足として、SMAP について簡単に整理します。
-
SMAP(Source Map)は JSR-045 で定義された仕組み
-
主に JSP などのコード生成結果と元ソースとの対応付けを可能にするためのもの
-
Tomcat では JSP コンパイルを担当する
JspServletが SMAP を付与する機能を持ち、デフォルトで有効-
suppressSmap設定で無効化可能
-
今回の挙動から、
- Java ソース由来のクラスファイルに対する SMAP は Eclipse のデバッグ機構が関与している可能性が高い
- JSP 由来のクラスファイルの SMAP は Tomcat 側が担当している
と考えられます。
結論
「高度なソース・ルックアップを使用する(JRE 1.5 以上)」を無効化することは、デバッグ実行時にカバレッジを取得するための一つの回避策ではあります。
しかし、より重要なのは次の点です。
JaCoCo は、実行時と解析時でクラス定義が一貫していることを前提としている
IDE のデバッグ構成では、SMAP などの形で 暗黙的なバイトコード改変が行われる可能性 があり、この前提が崩れます。
そのため、
カバレッジ計測は「実行(Run)」構成で行い、
デバッグ(Debug)構成は原因調査に専念する
という運用を推奨します。
デバッグ実行でカバレッジを取得しようとすること自体が、ツールの前提と相容れないケースがある、という点を理解しておくことが重要です。