Skip to content

IntelliJでJava 17から21にアップグレード後の「Java agent has been loaded dynamically」警告解決法

問題の原因

Java 17から21にアップグレード後にJUnitテストを実行すると、次のような警告が表示される場合があります:

text
WARNING: A Java agent has been loaded dynamically (...\byte-buddy-agent-1.14.9.jar)
WARNING: If a serviceability tool is in use, please run with -XX:+EnableDynamicAgentLoading to hide this warning
WARNING: If a serviceability tool is not in use, please run with -djdk.instrument.traceUsage for more information
WARNING: Dynamic loading of agents will be disallowed by default in a future release

この警告はJEP 451で導入された変更によるもので、Java 21から動的なエージェントロードが非推奨になったことが原因です。Mockitoなどのライブラリが内部で使用するByte Buddyエージェントが影響します。

警告メッセージは示唆していますが、-XX:+EnableDynamicAgentLoadingオプションを使うのは将来的な互換性の問題を引き起こす可能性があるため注意が必要です。

重要な注意点

-XX:+EnableDynamicAgentLoadingを使うと警告は表示されなくなりますが、将来的にJavaのバージョンアップ時に問題が発生する可能性があります。できるだけ静的エージェントロードに移行することが推奨されます。

永続的な解決策(ビルドツール別)

Mavenプロジェクトの場合

推奨される解決法maven-surefire-pluginでエージェントを静的にロードします:

xml
<build>
  <plugins>
    <!-- 依存関係のプロパティ取得を有効化 -->
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-dependency-plugin</artifactId>
      <version>${maven-dependency-plugin.version}</version>
      <executions>
        <execution>
          <goals>
            <goal>properties</goal>
          </goals>
        </execution>
      </executions>
    </plugin>
    
    <!-- エージェントを静的ロード -->
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-surefire-plugin</artifactId>
      <version>${maven-surefire-plugin.version}</version>
      <configuration>
        <argLine>@{argLine} -javaagent:${settings.localRepository}/org/mockito/mockito-core/${mockito.version}/mockito-core-${mockito.version}.jar</argLine>
      </configuration>
    </plugin>
  </plugins>
</build>

TIP

mockito.versionプロパティはpom.xmlで定義されている必要があります。例:

xml
<properties>
  <mockito.version>5.14.2</mockito.version>
</properties>

Gradleプロジェクトの場合

javaagent-testプラグインを使う方法(より将来性のあるアプローチ):

kotlin
// build.gradle.kts
plugins {
  id("com.ryandens.javaagent-test") version "0.8.0"
}

dependencies {
  testJavaagent("net.bytebuddy:byte-buddy-agent:1.15.11")
}

代替方法(エージェントローディングを有効化):

kotlin
// build.gradle
test {
  jvmArgs("-XX:+EnableDynamicAgentLoading")
}

Gradleユーザーへの注意

この問題はMockitoとGradleの間で公式に議論されています。公式対応を待つ場合、一時的な回避策として上記の方法を使用できます。

IntelliJ特有の設定

テストを「緑の矢印」(実行構成)から実行する場合、追加設定が必要です:

  1. プロジェクトの実行/デバッグ構成を開く
  2. テンプレート > JUnitを選択
  3. VMオプションに以下を追加(既存のオプションに続けて):
    text
    -javaagent:$MAVEN_REPOSITORY$/org/mockito/mockito-core/5.14.2/mockito-core-5.14.2.jar
    IntelliJの設定画面

重要な制限

  • エージェントのバージョンを明示的に指定する必要があります(ビルドツールのバージョンと同期されません)
  • 新しいテストクラスを実行すると新しい構成が作成されるため、毎回設定が必要です

その他の開発環境向け解決法

Eclipseユーザー向け

  1. 実行構成 > 引数タブを開く
  2. VM引数に以下を追加:
    text
    -Xshare:off
    -javaagent:${env_var:userprofile}\.m2\repository\org\mockito\mockito-core\5.14.2\mockito-core-5.14.2.jar
    Eclipse設定画面

グローバル環境変数設定(全プロジェクト影響)

Linux/macOS(.zshrcまたは.bashrc):

bash
export JDK_JAVA_OPTIONS="-XX:+EnableDynamicAgentLoading"

Windows:

  1. システム設定 > 環境変数
  2. 新規変数:
    • 変数名: JDK_JAVA_OPTIONS
    • 変数値: -XX:+EnableDynamicAgentLoading

注意事項

この方法はすべてのJavaアプリケーションに影響します。特定プロジェクトのみで問題を解決したい場合は推奨しません。

技術的背景とベストプラクティス

この警告は、Java 21で導入された新しいセキュリティポリシーに基づいています。次の点を考慮してください:

  1. 動的ロード vs 静的ロード:

    • 動的ロードは実行中にエージェントをロードするためセキュリティリスクがある
    • 静的ロード(-javaagent)は起動時にロードされるため安全
  2. ライブラリ選択:

  3. 今後の対応:

    xml
    <!-- 将来的に変更が必要な設定例 -->
    <argLine>-XX:+EnableDynamicAgentLoading</argLine> <!-- 非推奨アプローチ -->

推奨アプローチのまとめ

使用ツール推奨方法将来性
Maven静的エージェントロード
Gradlejavaagent-testプラグイン
IntelliJ(単体)JUnitテンプレート設定
Eclipse実行構成のVM引数

常に特定のプロジェクトのみに影響する解決法を選択し、グローバル設定は最終手段として使用してください。最新のライブラリバージョンを使用することで、互換性問題の発生確率を減らせます。

-XX:+EnableDynamicAgentLoadingは将来的なJavaバージョンで完全にサポートされなくなる可能性が高いため、公式ドキュメントやライブラリの変更ログを定期的に確認しましょう。