こんにちは、SREの戸田です。本日はJVM勉強会(運用編)に続けて開催したJVM勉強会(開発編)の一部を公開します。
システムプロパティ
システムプロパティは環境変数のように、プログラムの挙動を変えるために利用することが多いです。例えばOpenJDKそのものでも Integer.valueOf()
で値をどの程度キャッシュするか*1を設定するためにシステムプロパティを使っています。
他にも user.language
あたりはよく知られていますし、標準で提供されるシステムプロパティも多数あります。しかし製品コードから直接参照することは基本ないと思っていて、 File.pathSeparator
などの提供されたAPIを使うことが望ましいでしょう。またシステムプロパティは動的に変更することも可能ですが、システムプロパティを読み込む側がそれを想定しているかは確認したほうが良いでしょう。
文字コード
JVM自体はOS標準の文字コードを用いることになっていました。すなわちここは特に抽象化されておらず、プログラマが意識する必要がありました。 しかしJava 18からUTF-8が標準になるので、動作環境について気にする必要性がひとつ減ります。
逆に言えば、暗黙的にOS標準の文字コードを期待しているプログラムがあるならJava 18以降では注意が必要になります。医療機関向けシステムを扱っている弊社の場合だと、仕様としてShift_JISの利用を求めている書式がレセ電コード情報ファイルをはじめとして多数存在していることから、明示的に文字コードを指定する書き方を徹底することが必要です。
改行コード
JVM自体は改行コードの扱いを抽象化しません。このためプログラマがCR, LF, CRLFのいずれを使うか決定する必要があります。
とはいえOS標準の改行コードを使う場合は PrintWriter
, BufferedReader
, Scanner
といった標準ライブラリが提供する抽象化をもって対応すれば充分で、わざわざ System.lineSeparator()
などを利用して改行コードを明示的に扱うことは不要でしょう。
なお書式を扱うメソッドでは、Formaterが提供する %n
を使うことでOS標準の改行コードを参照することもできます。
マルチスレッドプログラミング
JVM/Javaはマルチスレッドプログラミングに向いているという話から入り、それでも考えることが結構あるよねという話で盛り上がりました。
特に InterruptedException
の扱いが複雑という点は、電車本(Java並行処理プログラミング)に詳しく説明されてるもののかなり古いため、最近の良い本を知りたいという声が複数出ました。おすすめの書籍がある読者の方はぜひ教えていただきたいです。
よくある落とし穴
JVMや標準ライブラリの挙動を知らないとハマる落とし穴がけっこうあり、以下に挙げるものを含めいくつか紹介しました。
- 正規表現のコンパイル処理はCPUに負荷をかけます。
kotlin.text.Regex
のコンストラクタやjava.lang.String
のmatches(String)
などがコンパイル処理を行うため、kotlin.text.Regex
インスタンスをcompanion objectに保存して使い回すなどの工夫が必要です。 SoftReference
やWeakHashMap
を使ってキャッシュを実装するのはGCの挙動に明るくても難しいため、メモリの利用状況に応じて挙動を変えるキャッシュが必要なら自分で実装せずにGuavaのようなライブラリを利用しましょう。- 配列の利用は極力避けて、コレクションを使いましょう。変更に柔軟で、メソッドも豊富に提供されています。あと配列はうっかり
Map
のキーなどに使うと困ったりとか、Javaのrecordで使うと問題があるとか、細かい落とし穴もちょいちょいあります。
JVMとタッグを組んで顧客価値にこだわるエンジニアを探しています
運用編と開発編の2回に分けて、JVMについて勉強会を開催しました。こうした機会を通してJVMの落とし穴を避けて性能を引き出すプログラムが書けるようになったり、システム運用のペインに刺さる監視が行えるようになると嬉しいです。
弊社では医療業界の業務改善のため、医療機関のERPと呼ぶべき電子カルテやレセプトコンピュータをSaaSとして開発・提供しています。JVM大好きな方も、TypeScriptどんと来いな方も求めておりますので、関心をお持ちの方はぜひ採用ページをご覧いただければと思います。よろしくお願いいたします。
*1:この話をしたらPythonにも似たようなキャッシュ機構があるという話が聞けて面白かったです、勉強会は話す側にもたくさん学びの機会があって良いですね