【ITニュース解説】Bugs wear data. Let's check Apache NiFi
2025年09月19日に「Dev.to」が公開したITニュース「Bugs wear data. Let's check Apache NiFi」について初心者にもわかりやすく解説しています。
ITニュース概要
Apache NiFiはデータ処理のオープンソースツールだ。静的解析ツールPVS-StudioがNiFiコード内の多様なバグを検出した。常に偽になる条件、コピーミス、NullPointerException、例外のスロー忘れ、型や文字列の比較間違いなど、具体的な欠陥が見つかった。静的解析によるバグの早期発見と修正の重要性を示す。
ITニュース解説
データ処理の現場では、情報の収集、加工、そして転送が非常に重要な役割を担っている。もしこれらのプロセスにプログラムのバグが潜んでいれば、システムの動作が不安定になったり、誤ったデータ処理が行われたりする可能性がある。この記事では、データ処理ツールであるApache NiFiというプロジェクトで見つかったいくつかのバグと、それらをどのように発見したのかについて説明する。
Apache NiFiは、データの収集、処理、移動を目的とした、無料で利用できるオープンソースのソフトウェアだ。もともとはアメリカ国家安全保障局(NSA)によって開発され、2014年にオープンソース化されて、Apacheソフトウェア財団のプロジェクトの一つとなった。現在では、特にHadoopのようなビッグデータ技術と組み合わせて、多くの大規模データプロジェクトで活用されている。NiFiの大きな利点は、そのわかりやすい視覚的なインターフェースにある。ユーザーは、まるで図を書くかのように、ドラッグ&ドロップで「プロセッサ」と呼ばれる処理ブロックを配置し、矢印でつなぐことでデータの流れ(データフロー)を簡単に設定できる。これにより、専門的な知識がなくても、データ管理者や分析者、開発者がデータの処理経路を構築できる。NiFiは、SFTPでファイルを転送したり、システムログ(syslog)を取り込んだり、データベース(JDBC経由)、Kafka、HDFS、Elasticsearchなど、非常に多様なデータソースに対応している。
今回、このApache NiFiプロジェクトのコードを、PVS-Studioという静的解析ツールを使って詳細にチェックした。静的解析とは、実際にプログラムを実行することなく、コードの記述内容から潜在的なバグや問題点を見つけ出す手法だ。NiFiプロジェクトには、PMDという別のコード品質管理ツールが既に導入されていたが、PVS-Studioがさらにどのようなエラーを発見できるかを検証した。
解析を行うにあたり、NiFiプロジェクトがMavenというビルドシステムを使っていたため、PVS-StudioのMavenプラグインを利用した。具体的には、プロジェクトの設定ファイルであるpom.xmlに数行の記述を追加し、PVS-Studioを有効化した。これにより、PVS-Studioがコードを解析し、その結果をJSON形式のレポートファイルに出力するように設定できた。解析時には、一般的なエラー診断ルールと、ウェブアプリケーションのセキュリティに関するOWASPの診断ルールグループを適用した。設定が完了した後、簡単なコマンド一つで解析が実行された。
PVS-Studioの解析によって、様々な種類のバグが発見された。その中からいくつか代表的な例を挙げる。
まず、論理的に常に真または偽になる条件式に関するバグが見つかった。あるコードでは、配列の長さをsplits.length < 0という条件でチェックしていた。しかし、配列の長さが負の値になることはプログラムの仕組み上ありえないため、この条件は常に偽となり、意味をなさない。開発者は配列が空であるかをチェックしたかったのかもしれないが、JavaのString.split()メソッドの特性により、たとえ区切り文字がない場合でも元の文字列を含む要素が一つ入った配列が返されるため、配列が空になる状況も発生しない。別のケースでは、ポートが削除された数を数えるprunedCountというカウンターがあったが、コード中でこのカウンターが増加する処理が抜けており、常に0のままだった。そのため、prunedCount == 0という条件式は常に真となり、意図した通りの処理が実行されなかった。
コードのコピー&ペーストが原因で発生したバグもあった。ある箇所では、if (A) {...} else if (A) {...}という形で同じ条件式が2回繰り返されていた。さらに悪いことに、2回目の処理ブロックでは、1回目と同じ変数名を誤って参照しており、本来比較すべきvalueObjectではなくkeyObjectを参照し続けていた。これは、開発者がコードをコピーした後に、修正すべき箇所を見落とした典型的なミスである。
例外処理に関するバグもいくつか検出された。一つは、エラーが発生した際に利用する例外オブジェクトをnew IllegalStateException(...)のように作成したものの、それを実際にプログラムに「投げ出す(throwする)」キーワードが記述されていなかったケースだ。これでは、例外オブジェクトは作成されるだけで、システムはそのエラーを認識せず、対処することができない。また別の例では、例外オブジェクトtがnullでないかをチェックする前に、tの中身を使おうとしている箇所があった(Throwables.stringStackTrace(t))。厳密には、このケースでは実際に渡されるtがnullになることはないため、即座にエラーにはならないが、コードの論理的な整合性に問題があるとして警告された。これは、例外を処理するメソッド内で、例外オブジェクトがnullかもしれないという状況に対するケアが不足していることを示していた。
NullPointerExceptionの原因となるバグもいくつか見つかった。あるコードでは、newStatusという変数がnullである可能性をif (newStatus == null)という条件でチェックしていた。しかし、その直後のコードでは、newStatusがnullではないことを前提としてnewStatus.getState()のようにその中身にアクセスしようとしていた。もしnewStatusがnullだった場合、プログラムはエラーで停止してしまう。同様に、childという変数がnullでないかをif (child != null)で確認しているにもかかわらず、その条件ブロックの外でchild.getPath()のように中身を呼び出す箇所もあった。これらのバグは、nullチェックの後に、そのチェックの結果を適切に反映した処理が行われていないために発生する。
オブジェクトの比較に関する間違いも多く見られた。あるコードでは、AllowableValueというオブジェクトと、ただの文字列(String)をequals()メソッドで比較しようとしていた。AllowableValueはgetValue()というメソッドで比較可能な文字列を返すため、このメソッドを呼び出してからequals()を使うべきだった。このような型が異なるオブジェクト間の不適切な比較は、常に意図しない結果を生む可能性がある。また、文字列を比較する際に==演算子を使っていた箇所もあった。Javaにおいて==はオブジェクトのメモリ上の位置が同じであるかを比較するもので、文字列の内容が同じであっても、メモリ上の位置が異なれば「別物」と判断してしまう。文字列の内容を比較するには、equals()メソッドを使うのが正しい方法である。さらに、equalsメソッドのオーバーライド内でArrays.equals()を使って二つの配列を比較する際に、比較対象の一方が、本来比較すべき別のオブジェクトではなく、自身の同じメソッドの呼び出し結果と比較されているというミスも見つかった。これも、コードのコピー&ペーストミスが原因で、常に同じ配列同士を比較してしまうため、正しいオブジェクトの同等性判定ができていなかった。
最後に、メッセージのフォーマットに関するバグも発見された。String.format()メソッドでメッセージを作成する際に、メッセージ中のプレースホルダの数と、実際にそのプレースホルダに埋め込まれる引数の数が合っていない箇所があった。開発者がロギングフレームワークの構文とString.format()の構文を混同してしまったために発生したもので、これにより、期待通りの正確なメッセージが出力されない可能性があった。
このように、PVS-Studioという静的解析ツールを使うことで、Apache NiFiのような大規模なオープンソースプロジェクトにおいても、既存の品質管理ツールでは見つけられなかった多くの種類のバグを発見できた。プログラム開発において、誰もがミスを犯すことは避けられない事実である。しかし、重要なのは、そうしたバグをいかに早く、効率的に見つけ出し、修正するかという点だ。静的解析ツールは、そのようなコード品質の維持と向上に大いに貢献できるツールである。