Java17で発生するSpotlessのエラーを解消する方法

こんにちは。 エキサイト株式会社の三浦です。

Javaで開発をする際、Spotlessを使用している方もいるのではないでしょうか。

このSpotlessですが、実は特定の状況下だとJava17で実行できない場合があります。

今回は、その状況と解決法について説明します。

Spotlessとは

Spotlessは、コードフォーマッタの1つです。

github.com

例えばJavaのGradleであれば、以下のように設定するだけで簡単に使えます。

build.gradle

// spotlessをimport
plugins {
  id "com.diffplug.spotless" version "6.10.0"
}

spotless {
  java {
    // フォーマット設定を記述
  }
}

実行

./gradlew spotlessApply

これだけで簡単にコードをフォーマットしてくれます。

非常にお手軽で便利ですが、Java17で使用しようとするとエラーが発生する場合があります。

Java17で実行する方法

例えば、以下の設定をJava17で実行してみます。

spotless {
  java {
    removeUnusedImports()
  }
}

すると、以下のエラーが起きてしまいます。

Caused by: java.lang.IllegalAccessError: class com.google.googlejavaformat.java.RemoveUnusedImports (in unnamed module ***) cannot access class com.sun.tools.javac.util.Context (in module jdk.compiler) because module jdk.compiler does not export com.sun.tools.javac.util to unnamed module ***

Java17のひとつ前のLTSバージョンであるJava11では起きないのですが、Java17になる過程で一部の設定が変わり、このエラーが出るようになったようです。

このエラーを回避するには、JVMに引数を渡す必要があります。

org.gradle.jvmargs=--add-exports jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED \
    --add-exports jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED \
    --add-exports jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED \
    --add-exports jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED \
    --add-exports jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED

これにより、問題なく実行できるようになります。

最後に

Javaのバージョンアップは、さまざまな新機能が使えるようになったりパフォーマンスが良くなったりなどいいことがたくさんありますが、一方で今回のように調整が必要な部分も出てきます。

とはいえ古いバージョンはいずれサポートされなくなっていくので、頑張ってバージョンアップしていくようにしましょう。