334.Java 21 で、ちょっとしたトラブル
初回:2023/10/18
今回のお話は、Pythonではなく、Javaのお話です。
P子「Java ならストレスは余りないの?」※1
Python は、触れば触るほど、不満が蓄積していきます。でも、最近のJavaは、色々と難しくなってきているので、よく判らなくなってきました。
P子「そんなしてまで、Pythonを使わなくてもいいんじゃないの?」
色々と考慮すると、嫌でもPythonで組む方が、トータルとして楽なんです。
1.Java の LTSリリース
まず、ものすごく基本的な事からおさらいしておきます。
Javaは業務システムとして使用しているので、基本的には、Long-Term-Support (LTS)リリース版しか使っていません。先のバージョンは、Java SE 17 を使っていましたが、今現在の最新版として、Java SE 21 が出ましたので、そちらに乗り換えようと思いました。
≪参考1≫
https://www.oracle.com/jp/java/technologies/java-se-support-roadmap.html
Oracle Java SE Supportロードマップ
(2023年9月18日更新)
基本的な考え方としては、LTS版ではないバージョン、例えば、Java 18,19,20 については、Support期限が 6か月だけなので、業務システムとしては利用できません。新機能とか、次期バージョンに向けた試作機能の確認用と考えるのが良いでしょう。私は非LTS版については、ほとんどノーチェックでしたので、いきなり、17 → 21 にバージョンアップして確認しているので、既存システムをコンパイルすると、警告がたくさん出ます。
この警告対応に結構時間を取られてしまいました。
それらの警告は、チェックが厳しくなって出される警告と、deprecation(非推奨)となった警告があります。チェックが厳しくなった警告は、きちんとしたコーディングをすればよいので、それはそれとして、対処すればよいでしょう。問題は、deprecation(非推奨)となった警告は、代替えメソッドを使うように変更するのですが、これがなかなか、難しい事でした。
それらの警告対応については、個々のソースコードの作りに依存するので、各自で頑張ってください。
2.デフォルトのエンコードがぁ‥‥
これらの警告とは別に、困ったことが発生しました。
私は、Javaのコンパイルやファイルのコピーなどを Apache Ant (https://ant.apache.org/) を使っています。その中で、javadoc タスクの出力が文字化けしました。日本語関連の文字化けには、昔から悩まされ続けていますが、『またか~』という感じでしたが、javadoc タスク関連の文字コードとか色々変更してみても、一向に直りません。
P子「いつも、文字化け関連の対応って、手当たり次第にエンコードを指定してたものね」
結構、理屈で解決しない事もあるので、そういう手法も『あり』かなと思ってます。
P子「『ant』だけに『あり』かもね」
そこで、ものすごく嫌な予感がして、確認してみました。
結論を書く前に、皆さんにもご自身で確認できる手法を記載しておきたいと思います。
java のインストールフォルダから、bin/jshell.exe を起動します。この、jshell というのは、Javaプログラミング言語を学習したり、およびJavaコードのプロトタイプを作成するための対話型ツールです。今回、お見せする確認ソースは、2行しかないので、javaソースファイルを作成してコンパイルして実行して...なんて邪魔くさいので、jshell を使ってみました。
ちなみに、Javaの実行環境は、Windows10です。
jshell> import java.nio.charset.Charset;
jshell> var charset = Charset.defaultCharset();
charset ==> windows-31j
jshell>
jshell> import java.nio.charset.Charset;
jshell> var charset = Charset.defaultCharset();
charset ==> UTF-8
jshell>
見てお分かりになるように、上が、Java 17 で、下が、Java 21 です。
な、なんと、Charset.defaultCharset() の値が、windows-31j から、UTF-8 に変更されています。
Java 17 のAPIを確認すると、https://docs.oracle.com/javase/jp/17/docs/api/java.base/java/nio/charset/Charset.html#defaultCharset()
public static Charset defaultCharset()
このJava仮想マシンのデフォルトの文字セットを返します。
デフォルトの文字セットは仮想マシンの起動時に決定されますが、それは通常、オペレーティング・システムのロケールと文字セットによって決まります。
Java 21 のAPIを確認すると、https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/nio/charset/Charset.html#defaultCharset()
public static Charset defaultCharset()
Returns the default charset of this Java virtual machine.
The default charset is UTF-8, unless changed in an implementation specific manner.
Implementation Note:
An implementation may override the default charset with the system property file.encoding on the command line. If the value is COMPAT, the default charset is derived from the native.encoding system property, which typically depends upon the locale and charset of the underlying operating system.
P子「英語じゃ判らないわよ」
この Java 仮想マシンのデフォルトの文字セットを返します。
実装固有の方法で変更しない限り、デフォルトの文字セットは UTF-8 です。
実装メモ
実装では、コマンド ラインのシステム プロパティ file.encoding を使用してデフォルトの文字セットをオーバーライドできます。 値が COMPAT の場合、デフォルトの文字セットは、native.encoding システム プロパティから派生します。これは通常、基礎となるオペレーティング システムのロケールと文字セットに依存します。
defaultCharset の値を戻さないと、現状の ant ではうまく javadocタスクを処理できていないようなので、複雑なことは取り置いて、file.encoding を使用してデフォルトの文字セットをオーバーライドしてみました。
ant 実行用のバッチファイルに、以下の1行を追加することで、とりあえず、javadoc タスクの日本語文字化けは回避できました。
set ANT_OPTS="-Dfile.encoding=Windows-31J"
3.まとめ
ant については、とりあえず上記方法で対処できましたが、色々な所で問題が出そうです。この手の日本語(英語圏以外の言語)だけに関連する問題は、気づかれにくいんだと思います。
また、警告を見ていて、『警告: [deprecation] Runtimeのexec(String,String[],File)は推奨されません』 とか、String 部分のコマンド文字列が、配列で指定することになりましたが、既存のプログラムを対応するのには、骨が折れそうです。
P子「単純にコマンドをスペースで分割すると、スペースを含むファイル名とかでバグりそうね」
色々と確認事項が多そうなので、正式に Java 21 に対応させるのに、いましばらく時間がかかりそうです。
ほな、さいなら
======= <<注釈>>=======
※1 P子「Java ならストレスは余りないの?」
P子とは、私があこがれているツンデレPythonの仮想女性の心の声です。