5 つの静的 Java コード アナライザーのレビュー
出典:
DZone 開発者は多くの場合、開発初期に誤ったコードを見つけて修正できる静的コード アナライザーなどのさまざまなプログラムを必要とします。コード レビューはこの取り組みにおいて非常に貴重なツールですが、場合によっては、コード レビュー担当者がレビューしなければならない量の多さに気が遠くなることがあります。これには多くの時間と労力がかかります。これは、レビュー担当者がプログラムの動作にとって重要なコードの断片のみに注意を払うことが多いという事実にもつながります。一方、静的分析ツールはすべてのコードを同じ精度でチェックします。
IntelliJ IDEA と互換性のあるコード アナライザーをいくつかまとめました。これがあなたの仕事に役立つことを願っています。
組み込みのIntelliJ IDEAアナライザー
IntelliJ IDEA に組み込まれている静的 Java コード アナライザーは、特殊な静的分析ツールに劣るものではありません。疑わしいコード、乱雑なコード、または正しくないコード フラグメントの検索は、データ フロー分析やパターン マッチングなどのさまざまな静的分析手法を使用して実行されます。IntelliJ IDEA には多数の検査があります。実際のところ、それらの多くは常にエラーを正確に報告するとは限りません。むしろ、コードがずさんであること、またはコードを適切な代替案に変更する可能性を示しています。「検査→Java」を少し勉強してみて、一つ気づいたことがあります。考えられるエラー、数値的問題、シリアル化の問題のカテゴリーで検査すると、実際のエラーが見つかる可能性が高くなります。いずれの場合も、自分でテストを実施し、どれがプロジェクトに役立つかを判断する必要があります。静的分析はコード編集モードで実行されるため、IntelliJ IDEA では、エラーが発生してから数秒以内にエラーを修正できます。エディターは、間違ったコード部分を即座に強調表示します。
本当に便利でカッコいいですね!さらに、選択したコード部分で「Alt + Enter」の組み合わせを使用すると、コンテキスト メニューからオプションの 1 つを選択してエラーを修正できます。また、特定のインスペクションを実行する理由を調べることもできます
。場合によっては、これにより検索時間が短縮されます。
「分析 → コードのチェック」を選択すると、分析を手動で実行できます。または、「分析→名前によるチェックを実行」を使用して個別のチェックを実行することもできます。これを行う前に、分析の範囲 (プロジェクト、モジュール、または個々のファイル) を指定します。この方法で分析を実行すると、複雑さのために編集モードでは機能しない一部のインスペクションが利用可能になります。分析後、結果は別のウィンドウでカテゴリ/ディレクトリごとにグループ化されます。このウィンドウから、特定の検証トリガーに移動できます。IntelliJ では、
分析結果を HTML および XML 形式で保存することのみが可能です。残念ながら、私の意見では、検出された問題を IDE 自体で処理するのが最も便利です。注記。静的アナライザーの機能のほとんどは、無料の IntelliJ IDEA Community Edition で利用できます。
ソナーJava
SonarJava は、SonarSource の Java 用静的コード アナライザーです。その機能のリストには次のものが含まれます。
分析は、さまざまな IDE (
SonarLintプラグイン経由) で実行することも、 SonarQubeで個別に実行することもできます。SonarLint は、組み込みの IntelliJ IDEA コード アナライザーと並行して動作できます。ハイライト表示されたコード部分にマウスを移動すると、多くの場合、両方のアナライザーからの警告が表示されます。
もちろん、警告は別のウィンドウで表示できます。
全体として、SonarJava をさまざまな方法で実行できる点が魅力的です。これにより、開発者はコードを記述するときにツールを自由に選択できます。
FindBugs/SpotBugs
残念ながら、
FindBugs は長い間更新されておらず、最後の安定版リリースは 2015 年にリリースされました。しかし、これはおそらく最も有名な無料の静的 Java コード アナライザーであるため、私たちは今でもそれを覚えていて使用しています。Java 開発者に静的分析について尋ねると、おそらくすぐに FindBugs を思い浮かべるでしょう。オープンソース アナライザー
SpotBugs は、放棄された FindBugs の論理的な継続となりました。FindBugs の長所と短所をすべて備えています。これが良いか悪いかは時間が経てばわかります。それまでの間、アナライザー コミュニティは積極的に開発を行っています。SpotBugs の主な特徴:
- 400以上のエラー検出ルール。
- Ant、Maven、Gradle、Eclipse、IntelliJ IDEA への統合。
- カスタム診断ルールで拡張可能。
疑わしいコードを見つけるには、パターン マッチングとデータ フロー分析という同じ手法が使用されます。アナライザーは、マルチスレッド、パフォーマンス、脆弱性、コードの難読化などに関連するさまざまな種類のエラーを検出します。IntelliJ IDEA では、アラート ウィンドウは次のようになります。
アラートは、カテゴリ、クラス、ディレクトリ、および信頼レベルごとにグループ化できます。診断ルールのアラートとドキュメントを同時に表示できます。分析は手動で開始されます。分析後、問題のあるすべてのコードフラグメントが、IntelliJ IDEA および SonarLint からの他の警告とともに強調表示されます。ただし、問題があります。ファイルに加えた変更を反映するには、分析を再実行して警告を更新する必要があります。また、多くの勧告警告があるため、アナライザーを実際に使用する前に設定する必要があります。
PVS スタジオ
PVS-Studio は、オープンソース ライブラリ Spoon に基づいています。ソース コードを入力として受け取り、セマンティック情報を備えた適切に設計された AST モデルを構築します。このモデルに基づいて、アナライザーは次のような最新の技術を使用します。
- データフロー分析。
- 象徴的なパフォーマンス。
- メソッドのアノテーション。
- パターンベースの分析。
現在、アナライザーは
105を超える診断ルールを使用して、さまざまなコードの欠陥を特定します。これには、タイプミスの修正、null 参照の名前変更、到達不能なコード、範囲外の配列インデックス、メソッド コントラクトの使用法違反、その他のエラーが含まれます。
すべての診断ルールの機能については、ここで確認できます。PVS-Studio の主な機能:
- アナライザーは実際のエラーを見つけることに重点を置いています。
- CLI バージョンに加えて、IntelliJ IDEA、Maven、Gradle、Jenkins、SonarQube との統合もあります。
- アナライザーを増分モードで実行する機能。
- アナライザーは、プロジェクトを Java 8 から新しいバージョンに移行する際に、Java SE API との潜在的な互換性の問題を特定します。
- PVS-Studio は、レポートをさまざまな使いやすい形式 (JSON、XML、HTML、TXT) に変換します。
- 特殊な SAST ツール: ほとんどの診断ルールはCWE、CERT、OWASPに従ってコンパイルされています。
PMD
PMD はオープンソースの静的アナライザーです。未使用の変数、空のブロック、不要なオブジェクトの作成、その他の問題など、一般的な開発エラーを特定します。アナライザーはソース コードを入力として使用します。現在、PMD はプロセスごとに 1 つのソース ファイルを分析するため、分析の完全性には制限があります。PMD の作成者は、分析の前にプロジェクトを組み立てることをアドバイスしています。これにより、分析中のコードで使用されている型に関する情報を抽出できます。PMD の主な機能:
- さまざまな IDE (IntelliJ IDEA、Eclipse、NetBeans) およびビルド システム (Maven、Gradle、Ant) との統合。
- さまざまなアナライザー レポート形式をサポート: SARIF、CSV、IDEA、JSON、テキスト (デフォルト)、XML、HTML、TextColor など。
- 300を超える診断ルール テンプレートがあります。カテゴリ: コーディング スタイル、ベスト プラクティス、バグ、マルチスレッド、パフォーマンスなど。
- コード内の重複を検出する PMD とともに CPD (コピー/ペースト検出器) を提供します。
すべての診断ルールを見ると、PMD はコーディング スタイルの問題を解決し、明らかなエラーを検出することに重点を置いています。診断ルールは相互に競合する可能性があるため、アナライザーを使用する前に構成する必要があります。IntelliJ IDEA のプラグインを使用して分析を実行することもできますが、分析のために個々のファイルを選択することはできません。警告ウィンドウは次のようになります。
私の意見では、警告をファイルや非明白なメッセージごとにグループ化できないため、警告を扱うのはあまり便利ではありません。これらは、警告の上にマウスを移動した場合にのみ表示されます。
結論
もちろん、上で説明したアナライザーに加えて、他のソリューションもあります。有料 (Coverity、Klockwork、JArchitect) プログラムと無料 (Error Prone、Infer、Checkstyle) プログラムの両方があります。これらはすべて、間違ったコードやバグの可能性のあるコードが運用環境に到達するのを防ぐという 1 つのことに焦点を当てています。どのアナライザーがこのタスクに適しているかを判断する権利は私にはありません。しかし、データ フロー分析とシンボリック実行を開発するアナライザーは、コード内の実際のバグを見つける可能性が高くなります。静的アナライザーを選択する場合は、次の点に注意してください。
- さまざまな IDE への統合。
- 組立システムへの統合。
- サーバー上でアナライザーを起動するのが簡単。
- コード編集モードでエラーを検出する機能。
- 警告を簡単に処理できる機能。
- SAST の方向性。
- 誤検知の割合。
- 構成の複雑さ。
- すべての長所と短所を組み合わせると、最適と思われる静的アナライザーの数が決まります。
注: IntelliJ IDEA を頻繁に使用するため、IntelliJ IDEA に統合された例を提供しました。
Java ヒープおよびスタック メモリのエラー
出典:
DZone 次に、Java ヒープまたはスタック メモリで発生する可能性のある主なエラーを見ていきますが、その前に、これら 2 つの用語の意味を覚えておきましょう。
- ヒープ メモリは、Java オブジェクトが保存される特別なメモリ領域です。
- スタックメモリとは、メソッド呼び出し時に変数を格納するための一時メモリの領域です。
ヒープ メモリの問題を説明する主な例外は
java.lang.OutOfMemoryErrorです。
Java ヒープ スペース
このエラーは、Java プログラムがヒープ メモリ領域への新しいオブジェクトの割り当てに失敗した場合に発生します。
GC オーバーヘッド制限を超えました
Java プログラムはガベージ コレクションに時間がかかりすぎます。このエラーは、ガベージ コレクションがプログラム時間の 98% を占め、回復できるメモリ領域が 2% 未満の場合に表示されます。
public class OutOfMemoryErrorDemo {
public static void main(String[] args) {
int i = 0;
List<String> stringList = new ArrayList<>();
while (i < Integer.MAX_VALUE) {
i++;
String generatedString = new String( "Some string generated to show out of memory error example " + i);
stringList.add(generatedString);
}
}
}
ここで
、stringList には生成された文字列への参照が含まれているため、ガベージ コレクターは生成された文字列をメモリから削除できませんが、アプリケーション内のその他のガベージは削除しようとします。しかし、これでは十分ではありません。
要求されたアレイ サイズが VM の制限を超えています
このエラーは、ヒープに十分な領域がないときに配列を割り当てようとすると発生します。
public class OutOfMemoryErrorDemo {
public static void main(String[] args) {
long[] array = new long[Integer.MAX_VALUE];
}
}
メタスペース
メタスペース領域にクラス データ情報を入れる余地がない場合、このメッセージとともに例外がスローされます。
スワップ スペースがありません (理由によりサイズ バイトを要求しました。スワップ スペースが不足していますか?)
このエラーは、ネイティブ ヒープにメモリを割り当てることができなかった場合、またはそのサイズが不十分な場合に表示されます。
理由 stack_trace_with_native_method
ネイティブ Java インターフェイスまたはネイティブ メソッドがヒープ上にメモリを割り当てることができませんでした。
StackOverFlowError - メソッド呼び出しが多すぎる場合。通常、例外は内部に再帰を含むメソッドによってスローされます。
public class StackOverFlowErrorDemo {
public static void main(String[] args) {
recursiveMethod(2);
}
public static int recursiveMethod(int i) {
return recursiveMethod(i);
}
}
GO TO FULL VERSION