エンジニアとしてシステムの開発や保守を経験してきました。その中で障害が発生した場合は迅速な対応が求められるのはエンジニアの方々にとっては当たり前のことだと思います。
私自身も多くの障害対応を経験してきましたが、対応は容易でも調査に時間がかかるのはやはりNullPointerExceptionではないかと思っています。
NullPointerExcepitonとは?
恐らくこのエラーに遭遇した人はいないと思われるほど有名なエラーですが、以下のリンクを参照してください。
簡単なソースですがこんな感じですね。
public static void main(String[] args) {
String data = getSubstring(null);
System.out.println(data);
}
static String getSubstring(String str) {
String data = str.substring(3);
return data;
}
問題なのは言うまでもなく、
String data = str.substring(3);
strがnullなのに、文字列抽出しようものならばエラーになりますよね。
JDK11の環境で実施すると以下のエラーが出力されます。
Exception in thread "main" java.lang.NullPointerException
at nullSample.sample.getSubstring(sample.java:14)
at nullSample.sample.main(sample.java:6)
このような簡単なロジックであれば行数を見て原因を調査することも容易ですが、それなりの規模のシステムであったり途中参画したシステムでこの事象が発生すると、ログの調査から原因特定、事象再現など大変です。
特に大変と感じているのが原因特定で、「どこで」「なにが」「どういう条件で」を調べて対応するには時間も労力も使います。
そのために、各処理の前にnullチェックを行うというのは必要な処理であり、プログラム教育やOJTで最初に習うことの一つだと思います。
対策を講じるのは簡単でも、実際にエラーが発生すると調査が大変なのがこのエラーの厄介なところでしょう。
NullPointerExceptionのメッセージ改善
ここからがようやく本題ですが、JDK14のバージョンからNullPointerExceptionが改善されていました。(恥ずかしながら最近知りました。)
簡単に言うと、原因特定に必要な「どこで」「なにが」がわかりやすくなったというものです。
早速JDK14以降のバージョン(ここではJDK17を使用)で上記のロジックを実行してみました。
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "String.substring(int)" because "str" is null
at nullSample.sample.getSubstring(sample.java:14)
at nullSample.sample.main(sample.java:6)
エラーが発生した場所と理由がメッセージとして出力されていますね。
まとめ
長期間の開発や保守を行っていると、対象の開発や保守の環境の知識は深くなりますが日々改善されているJavaやその他のプログラミング言語に対して、エンジニアとしてもっとアンテナを広げていかなければなと思う今日この頃でした。