Java コンソール出力が文字化けする場合にやるべきこと


はじめに

Java 18 からJEP 400: UTF-8 by Defaultにより、デフォルトのエンコーディングが UTF-8 に統一されたため、Windows 環境での文字化けが頻出する。

対策としては、全て UTF-8 に統一してやるのが良い。

  • ソースコードを UTF-8 とする
  • システムプロパティ file.encoding を UTF-8 とする
  • システムプロパティ sun.stdout.encodingsun.stderr.encoding を UTF-8 とする
  • ターミナルを UTF-8 とする


システムプロパティの設定

システムプロパティの値は以下で確認できる。

public static void main(String[] args) {
    System.out.println("Java Runtime version      :" + System.getProperty("java.runtime.version"));
    System.out.println("Charset.defaultCharset()  :" + Charset.defaultCharset());
    System.out.println("----------------------------------------------");
    System.out.println("\"file.encoding\"          = " + System.getProperty("file.encoding"));
    System.out.println("\"native.encoding\"        = " + System.getProperty("native.encoding"));
    System.out.println("\"sun.jnu.encoding\"       = " + System.getProperty("sun.jnu.encoding"));
    System.out.println("\"sun.stdout.encoding\"    = " + System.getProperty("sun.stdout.encoding"));
    System.out.println("\"sun.stderr.encoding\"    = " + System.getProperty("sun.stderr.encoding"));
    System.out.println("----------------------------------------------");
    System.out.println("あいうえお");
}

Windows10 環境において、Gradle で作成したアプリケーションプロジェクトを、特別な設定無く ./gradlew run した場合以下の出力となる。

Java Runtime version      :21+35-LTS
Charset.defaultCharset()  :UTF-8
----------------------------------------------
"file.encoding"          = UTF-8
"native.encoding"        = MS932
"sun.jnu.encoding"       = MS932
"sun.stdout.encoding"    = null
"sun.stderr.encoding"    = null
----------------------------------------------
・ス・ス・ス・ス・ス・ス・ス・ス・ス・ス

sun.stdout.encodingsun.stderr.encoding は、設定が無い場合は native.encoding の値がそのまま使われる。

Windows Terminal(PowerShell)では、以下のように JAVA_TOOL_OPTIONS を設定できる。

$ENV:JAVA_TOOL_OPTIONS = '-Dsun.stdout.encoding=UTF-8 -Dsun.stderr.encoding=UTF-8'

システムプロパティで native.encoding は上書き設定できなかったので、sun.* は非公式オプションだが、こちらを設定。


この状態で実行ると以下の様になる。

> ./gradlew run
Picked up JAVA_TOOL_OPTIONS: -Dsun.stdout.encoding=UTF-8 -Dsun.stderr.encoding=UTF-8
Java Runtime version      :21+35-LTS
Charset.defaultCharset()  :UTF-8
----------------------------------------------
"file.encoding"          = UTF-8
"native.encoding"        = MS932
"sun.jnu.encoding"       = MS932
"sun.stdout.encoding"    = UTF-8
"sun.stderr.encoding"    = UTF-8
----------------------------------------------
縺ゅ>縺・∴縺・

なお、Gradle アプリケーションの場合は以下のように指定することもできる。

application {
    mainClass.set("xxx")
    applicationDefaultJvmArgs = listOf("-Dsun.stdout.encoding=UTF-8", "-Dsun.stderr.encoding=UTF-8")
}


ターミナルの設定

ターミナルのコード ページが MS932 となっている場合、

> chcp
現在のコード ページ: 932

UTF-8 に変更する。

> chcp 65001
Active code page: 65001

実行すれば「あいうえお」が表示される。

> ./gradlew run
Picked up JAVA_TOOL_OPTIONS: -Dsun.stdout.encoding=UTF-8 -Dsun.stderr.encoding=UTF-8
Java Runtime version      :21+35-LTS
Charset.defaultCharset()  :UTF-8
----------------------------------------------
"file.encoding"          = UTF-8
"native.encoding"        = MS932
"sun.jnu.encoding"       = MS932
"sun.stdout.encoding"    = UTF-8
"sun.stderr.encoding"    = UTF-8
----------------------------------------------
あいうえお


file.encoding=COMPAT

JEP 400: UTF-8 by Default により、file.encoding=COMPAT とすることで従来互換となる。

ソースファイルは UTF-8 とし、コンパイル時のエンコーディングは以下のように指定し、

tasks.withType<JavaCompile> {
    options.encoding = Charsets.UTF_8.name()
}

以下の指定とすることで、

> $ENV:JAVA_TOOL_OPTIONS = '-Dfile.encoding=COMPAT'
> chcp 932

以下のように実行することもできる。

> ./gradlew run
Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=COMPAT
Java Runtime version      :21+35-LTS
Charset.defaultCharset()  :windows-31j
----------------------------------------------
"file.encoding"          = windows-31j
"native.encoding"        = MS932
"sun.jnu.encoding"       = MS932
"sun.stdout.encoding"    = null
"sun.stderr.encoding"    = null
----------------------------------------------
あいうえお


まとめ

Java 18 からは、デフォルトのエンコーディングが UTF-8 となったことで、Windows 環境では文字化けが発生しがちである。

全て UTF-8 に統一しておくのが吉である。

> $ENV:JAVA_TOOL_OPTIONS = '-Dsun.stdout.encoding=UTF-8 -Dsun.stderr.encoding=UTF-8'
> chcp 65001
> ./gradlew run