Docs and Info
FindBugs 2.0
Demo and data
Users and supporters
FindBugs blog
Fact sheet
Manual
Manual(ja/日本語)
FAQ
Bug descriptions
Bug descriptions(ja/日本語)
Bug descriptions(fr)
Mailing lists
Documents and Publications
Links
Downloads
FindBugs Swag
Development
Open bugs
Reporting bugs
Contributing
Dev team
API [no frames]
Change log
SF project page
Browse source
Latest code changes
| # FindBugs Bug Descriptions This document lists the standard bug patterns reported by FindBugs version 3.0.1. ## Summary
Description | Category
--- | ---
BC: equals メソッドは引数の型を仮定するべきではない | Bad practice
BIT: ビット演算の符号をチェックする | Bad practice
CN: Cloneable を実装したクラスが clone メソッドを定義していないか、使用していない | Bad practice
CN: clone メソッドが super.clone() を呼び出していない | Bad practice
CN: Cloneable を実装していないクラスが clone メソッドを定義している | Bad practice
CNT: 既知の定数の雑な値を見つける | Bad practice
Co: 抽象クラスは共変な compareTo メソッドを定義している | Bad practice
Co: compareTo()/compare() は間違って float または double 値を処理する | Bad practice
Co: compareTo()/compare() は Integer.MIN_VALUE を返す | Bad practice
Co: 共変な compareTo メソッドの定義 | Bad practice
DE: 例外を捨てているかもしれないメソッド | Bad practice
DE: 例外を無視しているかもしれないメソッド | Bad practice
DMI: エントリセットの要素を加えることは、Entry オブジェクトの再利用のために失敗するかもしれない | Bad practice
DMI: Random オブジェクトが作成され1度しか使われない | Bad practice
DMI: コレクションを消去するために removeAll メソッドを使用しない | Bad practice
Dm: System.exit(...) を呼び出しているメソッド | Bad practice
Dm: 危険なメソッド runFinalizersOnExit を呼び出しているメソッド | Bad practice
ES: String パラメータを == や != を使用して比較している | Bad practice
ES: String オブジェクトを == や != を使用して比較している | Bad practice
Eq: 抽象クラスは共変な equals メソッドを宣言している | Bad practice
Eq: equals メソッドは互換性のないオペランドをチェックしている | Bad practice
Eq: compareTo(...) メソッドを定義して Object.equals() を使用しているクラス | Bad practice
Eq: equals メソッドはサブタイプのために失敗する | Bad practice
Eq: 共変な equals メソッドの定義 | Bad practice
FI: 空のファイナライザは削除するべき | Bad practice
FI: ファイナライザの明示的な呼び出し | Bad practice
FI: ファイナライザはフィールドを null にする | Bad practice
FI: ファイナライザはフィールドを null にするだけ | Bad practice
FI: ファイナライザはスーパークラスのファイナライザを呼び出していない | Bad practice
FI: ファイナライザはスーパークラスのファイナライザを無効にしている | Bad practice
FI: ファイナライザはスーパークラスのファイナライザを呼び出しているだけ | Bad practice
FS: 書式文字列は \n よりも %n を使用するべき | Bad practice
GC: 検査されない型への総称呼び出し | Bad practice
HE: equals メソッドは定義していますが hashCode メソッドは定義していないクラス | Bad practice
HE: equals メソッドを定義して Object.hashCode() を使用しているクラス | Bad practice
HE: hashCode メソッドを定義していますが equals メソッドは定義していないクラス | Bad practice
HE: hashCode メソッドを定義して Object.equals() を使用しているクラス | Bad practice
HE: equals メソッドを継承して Object.hashCode() を使用しているクラス | Bad practice
IC: スーパークラスは初期化中にサブクラスを使用している | Bad practice
IMSE: 疑わしい IllegalMonitorStateException のキャッチ | Bad practice
ISC: static メソッドだけを提供するクラスの不必要なインスタンス化 | Bad practice
It: Iterator.next() が NoSuchElementException をスローできない | Bad practice
J2EE: HttpSession への非直列化可能オブジェクトの格納 | Bad practice
JCIP: 不変クラスのフィールドは final にすべき | Bad practice
ME: public 列挙型メソッドが無条件にフィールドを設定するPublic enum method unconditionally sets its field | Bad practice
ME: 列挙型フィールドは public で可変である | Bad practice
NP: 戻り型が Boolean のメソッドが明示的に null を返している | Bad practice
NP: null を返すかもしれない clone メソッド | Bad practice
NP: equals メソッドは null の引数をチェックしていない | Bad practice
NP: null を返すかもしれない toString メソッド | Bad practice
Nm: クラス名は大文字から始めるべき | Bad practice
Nm: 例外クラスのように命名されているが、クラスは Exception から派生されていない | Bad practice
Nm: 紛らわしい名前のメソッド | Bad practice
Nm: フィールド名は小文字から始めるべき | Bad practice
Nm: Java の後のバージョンのキーワードである識別子を使用している | Bad practice
Nm: Java の後のバージョンのキーワードである識別子を使用している | Bad practice
Nm: メソッド名は小文字から始めるべきです | Bad practice
Nm: クラス名は実装されたインタフェースの単純名を遮るべきではない | Bad practice
Nm: クラス名はスーパークラスの単純名を遮るべきではない | Bad practice
Nm: 非常に紛らわしい名前のメソッド (多分意図的) | Bad practice
Nm: パラメータの間違ったパッケージのためにスーパークラスのメソッドをオーバーライドしていないメソッド | Bad practice
ODR: データベースリソースのクローズに失敗するかもしれないメソッド | Bad practice
ODR: 例外経路でデータベースリソースのクローズに失敗するかもしれないメソッド | Bad practice
OS: ストリームのクローズに失敗するかもしれないメソッド | Bad practice
OS: 例外経路でストリームのクローズに失敗するかもしれないメソッド | Bad practice
PZ: 繰り返しでエントリオブジェクトを再利用しない | Bad practice
RC: 定数への疑わしい参照比較 | Bad practice
RC: Boolean 値の疑わしい参照比較 | Bad practice
RR: InputStream.read() の戻り値を無視しているメソッド | Bad practice
RR: InputStream.skip() の戻り値を無視しているメソッド | Bad practice
RV: compareTo()/compare() の結果を無効にする | Bad practice
RV: 例外的戻り値を無視しているメソッド | Bad practice
SI: スタティックイニシャライザは、すべての static final フィールドが代入される前にインスタンスを作成する | Bad practice
SW: Swing メソッドは AWT イベントディスパッチスレッドから呼び出す必要がある | Bad practice
Se: 直列化可能クラスの非 transient で非直列化可能なインスタンスフィールド | Bad practice
Se: 非直列化可能クラスに直列化可能な内部クラスがある | Bad practice
Se: 非直列化可能な値を直列化可能クラスのインスタンスフィールドに格納している | Bad practice
Se: Comparator は Serializable を実装していない | Bad practice
Se: 直列化可能な内部クラス | Bad practice
Se: serialVersionUID が final ではない | Bad practice
Se: serialVersionUID が long ではない | Bad practice
Se: serialVersionUID が static ではない | Bad practice
Se: Serializable なクラスのスーパークラスで、引数なしコンストラクタを定義していない | Bad practice
Se: Externalizable なクラスが引数なしコンストラクタを定義していない | Bad practice
Se: readResolve メソッドの戻り値の型が Object で宣言されていない | Bad practice
Se: 直列化復元によって設定されない transient フィールド | Bad practice
SnVI: Serializable なクラスが serialVersionUID を定義していない | Bad practice
UI: クラスが拡張されるなら getResource の使い方は安全ではないかもしれない | Bad practice
BC: 不可能なキャスト | Correctness
BC: 不可能なダウンキャスト | Correctness
BC: toArray メソッドの結果の不可能なダウンキャスト | Correctness
BC: 常に false を返す instanceof | Correctness
BIT: 符号付きバイト値のビット加算 | Correctness
BIT: 互換性のないビットマスク | Correctness
BIT: ((...) & 0) == 0 なのか確かめている | Correctness
BIT: 互換性のないビットマスク | Correctness
BIT: 符号付きバイト値のビット論理和 | Correctness
BIT: ビット演算の符号をチェックする | Correctness
BOA: スーパークラスの Adapter で実装されるメソッドを誤ってオーバーライドしているクラス | Correctness
BSHIFT: シフト演算の正しくない構文解析の可能性がある | Correctness
BSHIFT: 32ビット int の-31から31の範囲を超えた量によるシフト | Correctness
DLS: return 文に無駄なインクリメントがある | Correctness
DLS: クラスリテラルの無効な代入 | Correctness
DLS: 上書きされたインクリメント | Correctness
DMI: 逆にされた引数 | Correctness
DMI: 月のための間違った定数値 | Correctness
DMI: 正確に表されない double から構築された BigDecimal | Correctness
DMI: hasNext メソッドで next メソッドを呼び出している | Correctness
DMI: コレクションは自分自身を含めるべきではない | Correctness
DMI: D'oh! 無意味なメソッド呼び出し | Correctness
DMI: 配列で hashCode メソッドを呼び出している | Correctness
DMI: int に対して Double.longBitsToDouble() を呼び出している | Correctness
DMI: コレクションへの無意味な呼び出し | Correctness
Dm: ランタイムリテンションなしで、アノテーションの存在を調べるためにリフレクションを使用することはできない | Correctness
Dm: ScheduledThreadPoolExecutor の最大プールサイズを変えようとする無駄な試み | Correctness
Dm: コアプールサイズが0の ScheduledThreadPoolExecutor の作成 | Correctness
Dm: EasyMock メソッドへの役に立たない/無意味な呼び出し | Correctness
Dm: Math.max と Math.min の間違った組み合わせ | Correctness
EC: equals メソッドを使用して配列と非配列を比較している | Correctness
EC: 配列の equals メソッド呼び出しは == と等価である | Correctness
EC: equals(...) メソッドを使用して互換性のない配列を比較している | Correctness
EC: equals(null) の呼び出し | Correctness
EC: equals メソッドを呼び出して無関係のクラスとインタフェースを比較している | Correctness
EC: equals メソッドを呼び出して異なる型のインタフェースを比較している | Correctness
EC: equals メソッドを呼び出して異なる型を比較している | Correctness
EC: 参照等価性を使用して異なる型を比較している | Correctness
Eq: equals メソッドは常に false を戻す | Correctness
Eq: equals メソッドは常に true を返す | Correctness
Eq: equals メソッドはクラスオブジェクトではなくクラス名を比較している | Correctness
Eq: 列挙型は共変な equals メソッドを定義している | Correctness
Eq: equals(Object) メソッドをオーバーライドしていない equals メソッドの定義 | Correctness
Eq: Object.equals(Object) をオーバーライドしていない equals メソッドの定義 | Correctness
Eq: equals メソッドはスーパークラスの equals メソッドをオーバーライドしているが、対称的ではないかもしれない | Correctness
Eq: 共変な equals メソッドを定義して、Object.equals(Object) を継承している | Correctness
FE: NaN への等価性のための絶望的なテスト | Correctness
FS: 書式指示子へ渡している引数に互換性がない | Correctness
FS: 与えられた引数の型は書式指示子に合致しません | Correctness
FS: printf スタイルの書式が期待されているところで MessageFormat が与えられている | Correctness
FS: 書式文字列で実際に使われるより、多くの引数が渡されている | Correctness
FS: 無効な書式文字列 | Correctness
FS: 書式文字列は足りない引数を参照している | Correctness
FS: 書式文字列ための前の引数がない | Correctness
GC: 型パラメータとメソッド引数に関係がない | Correctness
HE: ハッシュ化された文脈でハッシュ化できないクラスの使用がシグネチャで宣言されている | Correctness
HE: ハッシュデータ構造で hashCode メソッドのないクラスを使用している | Correctness
ICAST: int 値を long に変換して絶対時間として使用している | Correctness
ICAST: 整数値を double にキャストして Math.ceil() に渡している | Correctness
ICAST: 整数値を float にキャストして Math.round() に渡している | Correctness
IJU: run メソッドでの JUnit アサーションは JUnit によって通知されない | Correctness
IJU: TestCase は suite メソッドの間違った宣言をしている | Correctness
IJU: TestCase はテストがない | Correctness
IJU: TestCase は super.setup() を呼び出さない setUp メソッドを実装している | Correctness
IJU: TestCase は 非 static な suite メソッドを実装している | Correctness
IJU: TestCase は super.tearDown() を呼び出さない tearDown メソッドを実装している | Correctness
IL: コレクションは自分自身を追加している | Correctness
IL: 明らかな無限ループ | Correctness
IL: 明らかな無限再帰ループ | Correctness
IM: 整数剰余の結果の整数乗算 | Correctness
INT: int 値と long 定数との間違った比較 | Correctness
INT: 負でない値と負の定数またはゼロとの間違った比較 | Correctness
INT: 符号付きバイトの間違った比較 | Correctness
IO: オブジェクト出力ストリームへの追加は失敗に終わる | Correctness
IP: メソッドで読み取られずに上書きされているパラメータ | Correctness
MF: スーパークラスのフィールドを隠すフィールドを定義しているクラス | Correctness
MF: フィールドを隠す変数を定義しているメソッド | Correctness
NP: null 値を利用している | Correctness
NP: null 値を例外経路で利用している | Correctness
NP: null の引数をチェックしていないメソッド | Correctness
NP: 常に null 値のオブジェクトで close メソッドを呼び出している | Correctness
NP: null 値を利用することが保証されている | Correctness
NP: null 値を例外経路で利用することが保証されている | Correctness
NP: 非 null フィールドは初期化されていない | Correctness
NP: メソッド呼び出しは非 null パラメータに対して null を渡している | Correctness
NP: null を返すかもしれないメソッドが @Nonnull 宣言されている | Correctness
NP: null とわかっている値をその型のインスタンスなのか確かめている | Correctness
NP: null 値を利用している可能性がある | Correctness
NP: null 値を例外経路で利用している可能性がある | Correctness
NP: メソッド呼び出しは非 null パラメータに対して null を渡している | Correctness
NP: メソッド呼び出しは非 null パラメータに対して null を渡している | Correctness
NP: 非 null パラメータに null を渡している非仮想メソッドの呼び出し | Correctness
NP: Optional の戻り型を持つメソッドが明示的に null を返す | Correctness
NP: @Nonnull でアノテートされたフィールドに null を格納している | Correctness
NP: 書き込まれていないフィールドの読み出し | Correctness
Nm: クラスは equal(Object) を定義しています。equals(Object) にすべきですか? | Correctness
Nm: クラスは hashcode() を定義しています。hashCode() にすべきですか? | Correctness
Nm: クラスは tostring() を定義しています。toString() にすべきですか? | Correctness
Nm: 明らかなメソッドとコンストラクタの混乱 | Correctness
Nm: 非常に紛らわしい名前のメソッド | Correctness
Nm: パラメータの間違ったパッケージのためにスーパークラスのメソッドをオーバーライドしていないメソッド | Correctness
QBA: 論理式で boolean リテラル値を代入しているメソッド | Correctness
RANGE: 配列インデックスは範囲外 | Correctness
RANGE: 配列の長さは範囲外 | Correctness
RANGE: 配列オフセットは範囲外 | Correctness
RANGE: 文字列インデックスは範囲外 | Correctness
RC: 疑わしい参照比較 | Correctness
RCN: 既に利用していた値の null チェック | Correctness
RE: 正規表現のための無効な構文 | Correctness
RE: 正規表現のために使われている File.separator | Correctness
RE: 正規表現のために使われている "." または "|" | Correctness
RV: 0から1の乱数値は整数値0に丸められる | Correctness
RV: 符号付き32ビットハッシュコードの絶対値を計算する間違った試み | Correctness
RV: 符号付き整数の乱数の絶対値を計算する間違った試み | Correctness
RV: compareTo によって返された特定の値のコードチェック | Correctness
RV: 作成した例外をスローするのではなく捨てている | Correctness
RV: 戻り値を無視しているメソッド | Correctness
RpC: 条件テストの繰り返し | Correctness
SA: フィールドの自己代入 | Correctness
SA: フィールドとそれ自身との自己比較 | Correctness
SA: フィールドの無意味な自己演算 (たとえば、 x & x) | Correctness
SA: フィールドへの代入ではなくローカル変数への自己代入 | Correctness
SA: ローカル変数とそれ自身との自己比較 | Correctness
SA: 変数の無意味な自己演算 (たとえば、x & x) | Correctness
SF: switch 文のフォールスルーのために格納が無効になっている | Correctness
SF: スローする switch 文のフォールスルーのために格納が無効になっている | Correctness
SIC: 非 static 内部クラスとスレッドローカルのデッドロック | Correctness
SIO: instanceof 演算子を使用した不必要な型チェック | Correctness
SQL: インデックスが0で PreparedStatement にアクセスしようとしているメソッド | Correctness
SQL: インデックスが0で ResultSet にアクセスしようとしているメソッド | Correctness
STI: interrupted メソッドを呼び出すために不要な currentThread メソッドを呼び出している | Correctness
STI: スレッドインスタンスで static Thread.interrupted() を呼び出している | Correctness
Se: 直列化機構のために private にしなければならないメソッド | Correctness
Se: readResolve メソッドが static メソッドとして宣言されている | Correctness
TQ: 型修飾子でアノテーションされた値がその修飾子を付けてはならない値を必要とする場所で使われている | Correctness
TQ: 互換性のない型修飾子による比較値 | Correctness
TQ: 型修飾子を付けていないかもしれない値がその型修飾子を必要とする方法で常に使われている | Correctness
TQ: 型修飾子を付けているかもしれない値がその型修飾子を禁止する方法で常に使われている | Correctness
TQ: 型修飾子でアノテートされていない値がその修飾子が付けられた値を必要とする場所で使われている | Correctness
TQ: 型修飾子がない値が修飾子を必要とする場所で使われている | Correctness
UMAC: 呼び出し不可能なメソッドが無名クラスで定義されている | Correctness
UR: コンストラクタで初期化されていないフィールドを読み出している | Correctness
UR: スーパークラスのコンストラクタから呼び出されるメソッドで初期化されていないフィールドを読み出している | Correctness
USELESS_STRING: 名前のない配列で toString メソッドを呼び出している | Correctness
USELESS_STRING: 配列で toString メソッドを呼び出している | Correctness
USELESS_STRING: 書式文字列を使用して役に立たない方法で配列をフォーマットしている | Correctness
UwF: null に設定されるだけのフィールド | Correctness
UwF: 書き込まれていないフィールド | Correctness
VA: 可変長引数を期待しているメソッドにプリミティブ型の配列を渡している | Correctness
LG: ロガーの変更は OpenJDK の弱参照が原因で潜在的に失われる | Experimental
OBL: ストリームやリソースのクリーンアップに失敗するかもしれないメソッド | Experimental
OBL: チェック例外でストリームやリソースのクリーンアップに失敗するかもしれないメソッド | Experimental
Dm: 呼び出したメソッドの Locale パラメータの使用を検討する | Internationalization
Dm: デフォルトエンコーディングへの依存 | Internationalization
DP: doPrivileged ブロック内で作成されるべきクラスローダ | Malicious code vulnerability
DP: doPrivileged ブロック内で呼び出すべきメソッド | Malicious code vulnerability
EI: 可変オブジェクトへの参照を返すことによって内部表現を暴露するかもしれないメソッド | Malicious code vulnerability
EI2: 可変オブジェクトへの参照を取り込むことによって内部表現を暴露するかもしれないメソッド | Malicious code vulnerability
FI: ファイナライザは public ではなく protected にすべき | Malicious code vulnerability
MS: static フィールドに可変オブジェクトを格納することによって、内部の静的状態を暴露するかもしれないメソッド | Malicious code vulnerability
MS: final でないフィールドは悪意のあるコードから保護できない | Malicious code vulnerability
MS: 配列を返すことによって内部表現を暴露するかもしれない public static メソッド | Malicious code vulnerability
MS: final かつパッケージプロテクテッドにすべきフィールド | Malicious code vulnerability
MS: 可変配列のフィールド | Malicious code vulnerability
MS: 可変コレクションのフィールド | Malicious code vulnerability
MS: パッケージプロテクテッドにすべき可変コレクションのフィールド | Malicious code vulnerability
MS: 可変 Hashtable のフィールド | Malicious code vulnerability
MS: インタフェースから移動してパッケージプロテクテッドにすべきフィールド | Malicious code vulnerability
MS: パッケージプロテクテッドにすべきフィールド | Malicious code vulnerability
MS: final にすべきフィールド | Malicious code vulnerability
MS: final でないフィールドはリファクタリングするべき | Malicious code vulnerability
AT: 並行抽象の呼び出しシーケンスはアトミックではないかもしれない | Multithreaded correctness
DC: フィールドのダブルチェックの可能性 | Multithreaded correctness
DC: 部分的に初期化されたオブジェクトを暴露する可能性がある | Multithreaded correctness
DL: Boolean の同期化 | Multithreaded correctness
DL: デッドロックの原因になる可能性があるボクシングされたプリミティブ型の同期化 | Multithreaded correctness
DL: 正準化した文字列の同期化 | Multithreaded correctness
DL: ボクシングされたプリミティブ値の同期化 | Multithreaded correctness
Dm: Condition で wait メソッドを呼び出している | Multithreaded correctness
Dm: デフォルトの空の run メソッドを使用して作成されたスレッド | Multithreaded correctness
ESync: 空の synchronized ブロック | Multithreaded correctness
IS: 一貫性のない同期化 | Multithreaded correctness
IS: 並行アクセスに対してガードされていないフィールド | Multithreaded correctness
JLM: Lock で同期化している | Multithreaded correctness
JLM: java.util.concurrent のインスタンスで同期化している | Multithreaded correctness
JLM: util.concurrent 抽象でモニタスタイルの wait メソッドを使用している | Multithreaded correctness
LI: static フィールドの間違った遅延初期化 | Multithreaded correctness
LI: 更新される static フィールドの間違った遅延初期化 | Multithreaded correctness
ML: フィールドを同期化でガードしようとする無駄な試み | Multithreaded correctness
ML: 更新されるフィールドで同期化しているメソッド | Multithreaded correctness
MSF: 可変サーブレットフィールド | Multithreaded correctness
MWN: 不整合な notify メソッド | Multithreaded correctness
MWN: 不整合な wait メソッド | Multithreaded correctness
NN: 裸の notify メソッド | Multithreaded correctness
NP: 同じフィールドでの同期化と null チェック | Multithreaded correctness
No: notifyAll メソッドではなく notify メソッドを使用している | Multithreaded correctness
RS: readObject メソッドを同期化しているクラス | Multithreaded correctness
RV: putIfAbsent の戻り値は無視されて putIfAbsent に渡した値は再利用された | Multithreaded correctness
Ru: スレッドで run メソッドを呼び出している | Multithreaded correctness
SC: Thread.start() を呼び出しているコンストラクタ | Multithreaded correctness
SP: スピンロックをしているメソッド | Multithreaded correctness
STCAL: static Calendar の呼び出し | Multithreaded correctness
STCAL: static DateFormat の呼び出し | Multithreaded correctness
STCAL: static Calendar フィールド | Multithreaded correctness
STCAL: static DateFormat | Multithreaded correctness
SWL: ロックを保持して Thread.sleep() を呼び出しているメソッド | Multithreaded correctness
TLW: 2つ以上のロックを保持して wait メソッドを呼び出している | Multithreaded correctness
UG: 同期化していない get メソッド、同期化している set メソッド | Multithreaded correctness
UL: すべての経路でロックが解除されないメソッド | Multithreaded correctness
UL: すべての例外経路でロックが解除されないメソッド | Multithreaded correctness
UW: wait メソッドの無条件呼び出し | Multithreaded correctness
VO: volatile フィールドへのインクリメントはアトミックではない | Multithreaded correctness
VO: 配列への volatile 参照は、配列要素を volatile として扱わない | Multithreaded correctness
WL: クラスリテラルではなく getClass で同期化している | Multithreaded correctness
WS: writeObject メソッドは同期化しているがその他のメソッドは同期化していないクラス | Multithreaded correctness
Wa: Condition.await() がループの中にない | Multithreaded correctness
Wa: wait メソッドがループの中にない | Multithreaded correctness
Bx: プリミティブ値がボクシングされて、すぐにアンボクシングされる | Performance
Bx: プリミティブ値がプリミティブ型の型変換をするためにボクシングされて、アンボクシングされる | Performance
Bx: プリミティブ値が3項演算子のためにアンボクシングされて、型変換される | Performance
Bx: ボクシングされた値がアンボクシングされて、すぐに再ボクシングされる | Performance
Bx: プリミティブが比較でボクシングされている | Performance
Bx: ボクシング/アンボクシングはプリミティブを解析する | Performance
Bx: toString メソッドを呼び出すためにプリミティブ型のラッパクラスのインスタンスを作成している | Performance
Bx: 効率が悪い浮動小数点 Number コンストラクタを呼び出しているメソッド | Performance
Bx: 効率が悪い Number コンストラクタを呼び出しているメソッド | Performance
Dm: URL の equals メソッドと hashCode メソッドはブロックする | Performance
Dm: URL の Map や Set はひどい性能になる | Performance
Dm: 効率が悪い Boolean コンストラクタを呼び出しているメソッド | Performance
Dm: 明示的なガベージコレクション | Performance
Dm: クラスオブジェクトを得るためだけにインスタンスを作成しているメソッド | Performance
Dm: 整数の乱数を生成するためには nextDouble メソッド ではなく nextInt メソッドを使用する | Performance
Dm: 効率が悪い new String(String) コンストラクタを呼び出しているメソッド | Performance
Dm: String の toString メソッドを呼び出しているメソッド | Performance
Dm: 効率が悪い new String() コンストラクタを呼び出しているメソッド | Performance
HSC: 複数のクラスファイルにわたって複製されている巨大な文字列定数 | Performance
SBSC: ループの中で + を使用して文字列を連結しているメソッド | Performance
SIC: static 内部クラスにすべき | Performance
SIC: 名前付き static 内部クラスにリファクタリングできるかもしれない | Performance
SIC: static 内部クラスにリファクタリングできるかもしれない | Performance
SS: 読み出されないフィールド | Performance
UM: 定数値で Math クラスの static メソッドを呼び出しているメソッド | Performance
UPM: private メソッドは決して呼び出されない | Performance
UrF: 読み出されないフィールド | Performance
UuF: 未使用のフィールド | Performance
WMI: entrySet イテレータではなく効率が悪い keySet イテレータを使用している | Performance
Dm: ハードコードされた定数データベースパスワード | Security
Dm: 空のデータベースパスワード | Security
HRS: 信頼できない入力から形成された HTTP cookie | Security
HRS: HTTP レスポンススプリッティング脆弱性 | Security
PT: サーブレットの絶対パストラバーサル | Security
PT: サーブレットの相対パストラバーサル | Security
SQL: SQL の Statement の execute または addBatch メソッドに定数でない文字列を渡している | Security
SQL: PreparedStatement が定数でない文字列から生成されている | Security
XSS: 反射型クロスサイトスクリプティング脆弱性がある JSP | Security
XSS: 反射型クロスサイトスクリプティング脆弱性がエラーページにあるサーブレット | Security
XSS: 反射型クロスサイトスクリプティング脆弱性があるサーブレット | Security
BC: 抽象コレクションへの疑わしいキャスト | Dodgy code
BC: 具象コレクションへの疑わしいキャスト | Dodgy code
BC: 未チェック/未確認のキャスト | Dodgy code
BC: メソッドからの戻り値の未チェック/未確認のキャスト | Dodgy code
BC: 常に true を返す instanceof | Dodgy code
BSHIFT: 符号なし右シフトを short/byte にキャストしている | Dodgy code
CI: final なクラスが protected フィールドを宣言している | Dodgy code
DB: 2つの分岐のために同じコードを使用しているメソッド | Dodgy code
DB: switch 文の2つの case のために同じコードを使用しているメソッド | Dodgy code
DLS: ローカル変数への無効な代入 | Dodgy code
DLS: return 文に役に立たない代入がある | Dodgy code
DLS: ローカル変数への無効な null 代入 | Dodgy code
DLS: フィールドを遮るローカル変数への無効な代入 | Dodgy code
DMI: ハードコードされた絶対パス名への参照がある | Dodgy code
DMI: ObjectOutput に書き込まれる非直列化可能オブジェクト | Dodgy code
DMI: substring(0) の呼び出しは元の値を返す | Dodgy code
Dm: Thread オブジェクトが Runnable が期待されているところに渡されている | Dodgy code
Eq: スーパークラスの equals メソッドをオーバーライドしていないクラス | Dodgy code
Eq: 異常な equals メソッド | Dodgy code
FE: 浮動小数点の等価性のためのテスト | Dodgy code
FS: Boolean 型でない引数を ％b 書式指示子を使用してフォーマットしている | Dodgy code
IA: 潜在的な継承されたメソッドなのか外部のメソッドなのかあいまいなメソッドの呼び出し | Dodgy code
IC: 初期化が循環している | Dodgy code
ICAST: 整数の除算の結果を double または float にキャストしている | Dodgy code
ICAST: 整数乗算の結果を long にキャストしている | Dodgy code
IM: 平均の計算はオーバーフローする可能性がある | Dodgy code
IM: 負数で機能しない奇数チェック | Dodgy code
INT: 1を法とする整数の剰余 | Dodgy code
INT: 整数値の無意味なビットマスク演算 | Dodgy code
INT: 整数値の無意味な比較 | Dodgy code
MTIA: Servlet クラスを拡張したクラスでのインスタンス変数の使用 | Dodgy code
MTIA: Struts Action を拡張したクラスでのインスタンス変数の使用 | Dodgy code
NP: readLine メソッドの結果が null なのか確かめないで値を利用している | Dodgy code
NP: readLine メソッドの結果をすぐに利用している | Dodgy code
NP: null とわかっている値のロード | Dodgy code
NP: メソッドはパラメータに nullness アノテーションを強化している | Dodgy code
NP: メソッドは戻り値の nullness アノテーションを緩和している | Dodgy code
NP: null になっている可能性があるメソッドの戻り値を利用している | Dodgy code
NP: null 値を実行不可能かもしれない分岐で利用している可能性がある | Dodgy code
NP: パラメータは 非 null でなければならないが null 可能としてアノテートされている | Dodgy code
NP: 書き込まれていない public または protected フィールドの読み出し | Dodgy code
NS: 潜在的な非短絡論理の危険な使用 | Dodgy code
NS: 非短絡論理の疑わしい使用 | Dodgy code
PZLA: null ではなく長さが0の配列を返すことを検討する | Dodgy code
QF: 複雑か巧妙か間違ったインクリメントの for ループ | Dodgy code
RCN: 非 null 値と null 値との冗長な比較 | Dodgy code
RCN: 2つの null 値の冗長な比較 | Dodgy code
RCN: null でないことがわかっている値の冗長な null チェック | Dodgy code
RCN: null とわかっている値の冗長な null チェック | Dodgy code
REC: 例外がスローされないのに例外をキャッチしている | Dodgy code
RI: スーパークラスと同じインタフェースを実装しているクラス | Dodgy code
RV: String.indexOf の結果が正かどうか確かめている | Dodgy code
RV: readLine メソッドの結果を null でないのか確かめた後で捨てている | Dodgy code
RV: ハッシュコードの剰余は負かもしれない | Dodgy code
RV: 符号付き32ビット整数の乱数の剰余 | Dodgy code
RV: メソッドは戻り値を無視しています、これは間違いではないですか? | Dodgy code
RV: 副作用がないメソッドの戻り値は無視される | Dodgy code
SA: フィールドの二重代入 | Dodgy code
SA: ローカル変数の二重代入 | Dodgy code
SA: ローカル変数の自己代入 | Dodgy code
SF: 1つの case が次の case へと通り抜ける switch 文を発見した | Dodgy code
SF: default がない switch 文を発見した | Dodgy code
ST: インスタンスメソッドから static フィールドへの書き込み | Dodgy code
Se: サブクラスで継承できない private な readResolve メソッド | Dodgy code
Se: Serializable でないクラスの transient フィールド | Dodgy code
TQ: 値は型修飾子を必要としているが、不明としてマークされている | Dodgy code
TQ: 値は型修飾子を必要としないが、不明としてマークされている | Dodgy code
UC: 条件は効果がない | Dodgy code
UC: 条件は変数型のために効果がない | Dodgy code
UC: 役に立たないオブジェクトを作成した | Dodgy code
UC: 役に立たないオブジェクトをスタックで作成した | Dodgy code
UC: 役に立たない空ではない void メソッド | Dodgy code
UCF: 役に立たない制御フロー | Dodgy code
UCF: 次の行へ続くだけの役に立たない制御フロー | Dodgy code
UrF: 読み出されない public または protected フィールド | Dodgy code
UuF: 未使用の public または protected フィールド | Dodgy code
UwF: コンストラクタで初期化されていないフィールドを null チェックなしで null 値を利用している | Dodgy code
UwF: 書き込まてれいない public または protected フィールド | Dodgy code
XFB: XMLインタフェースの特定の実装のインスタンスを作成しているメソッド | Dodgy code
> ## Descriptions ### BC: equals メソッドは引数の型を仮定するべきではない (BC_EQUALS_METHOD_SHOULD_WORK_FOR_ALL_OBJECTS) `equals(Object o)` メソッドは、`o` の型についてどんな仮定もするべきではありません。 `o` が `this` と同じ型でないなら単に false を返すべきです。 ### BIT: ビット演算の符号をチェックする (BIT_SIGNED_CHECK) このメソッドは、`((event.detail & SWT.SELECTED) > 0)` のような式を比較しています。 ビット演算をより大きい演算子で比較することは、予想外の結果 (もちろん、`SWT.SELECTED` の値による) の原因になる可能性があります。 `SWT.SELECTED` が負数であるなら、これはバグの候補です。 `SWT.SELECTED` が負ではないとしても、'> 0' の代わりに '!= 0' を使用することは良いプラクティスと思われます。 Boris Bokowski ### CN: Cloneable を実装したクラスが clone メソッドを定義していないか、使用していない (CN_IDIOM) このクラスは、`Cloneable` を実装していますが、`clone` メソッドを定義していないか使用していません。 ### CN: clone メソッドが super.clone() を呼び出していない (CN_IDIOM_NO_SUPER_CALL) この非 final クラスは、`super.clone()` を呼び出さない `clone` メソッドを定義しています。 クラス A がサブクラス B によって拡張され、サブクラス B が `super.clone()` を呼び出すなら、クラス B の `clone` メソッドは、型 A のオブジェクトを返す可能性が高いです。 これは `clone` のための汎用規約に違反します。 すべての `clone` メソッドが `super.clone()` を呼び出すなら `Object.clone()` が呼び出されることが保証され、常に正しい型のオブジェクトが返されます。 ### CN: Cloneable を実装していないクラスが clone メソッドを定義している (CN_IMPLEMENTS_CLONE_BUT_NOT_CLONEABLE) このクラスは、`Cloneable` を実装していないのに `clone` メソッドを定義しています。 これが OK (たとえば、サブクラスのクローンの実装を自分自身で制御したい場合です) という状況もありますが意図したことなのか確認してください。 ### CNT: 既知の定数の雑な値を見つける (CNT_ROUGH_CONSTANT_VALUE) コードの明確さともっと良い正確さのために定義済みライブラリ定数を使用することを推奨します。 ### Co: 抽象クラスは共変な compareTo メソッドを定義している (CO_ABSTRACT_SELF) このクラスは、共変な `compareTo` メソッドを定義しています。 `Comparable` インタフェースの `compareTo` メソッドを正しく実装するためには `compareTo` メソッドのパラメータの型は、`java.lang.Object` でなければなりません。 ### Co: compareTo()/compare() は間違って float または double 値を処理する (CO_COMPARETO_INCORRECT_FLOATING) このメソッドはこのようなパターンを使用して double または float 値を比較しています ： val1 > val2 ? 1 : val1 < val2 ? -1 : 0。 このパターンは 正しくないソート結果や壊れたコレクションの原因になるかもしれない -0.0 や NaN 値のために間違って働きます （もし比較された値がキーとして使われるなら）。 すべての特殊なケースを正確に処理するために Double.compare または Float.compare メソッドの使用を検討してください。 ### Co: compareTo()/compare() は Integer.MIN_VALUE を返す (CO_COMPARETO_RESULTS_MIN_VALUE) いくつかの状況下では、この `compareTo` または `compare` メソッドは Integer.MIN_VALUE を返します。ひどいバッドプラクティスです。 `compareTo` メソッドの戻り値で重要なことは結果の符号だけです。 しかし、結果の符号を無効にすることを期待して、`compareTo` メソッドの戻り値を無効にすることがあります。 返された値が Integer.MIN_VALUE の場合を除いてです。 Integer.MIN_VALUE よりも-1を返してください。 ### Co: 共変な compareTo メソッドの定義 (CO_SELF_NO_OBJECT) このクラスは、共変な `compareTo` メソッドを定義しています。 `Comparable` インタフェースの `compareTo` メソッドを正しく実装するためには `compareTo` メソッドのパラメータの型は、`java.lang.Object` でなければなりません。 ### DE: 例外を捨てているかもしれないメソッド (DE_MIGHT_DROP) このメソッドは、例外を捨てているかもしれません。 一般的にキャッチした例外は何らかの方法で処理、または報告するべきです、またはメソッドからスローするべきです。 ### DE: 例外を無視しているかもしれないメソッド (DE_MIGHT_IGNORE) このメソッドは例外を無視しているかもしれません。 一般的に例外は何らかの方法で処理、または報告するべきです、またはメソッドからスローするべきです。 ### DMI: エントリセットの要素を加えることは、Entry オブジェクトの再利用のために失敗するかもしれない (DMI_ENTRY_SETS_MAY_REUSE_ENTRY_OBJECTS) entrySet メソッドは、一つの Entry オブジェクトを再利用し、反復中に返される基底 Map のビューを返すことが許可されています。 Java 1.6 の時点で、IdentityHashMap と EnumMap の両方がそうしました。 そのような Map を通して繰り返すとき、エントリ値は次の繰り返しへ進むまでが有効です。 たとえば、addAll メソッドにそのような entrySet を渡そうと試みるのは、ひどく間違っているでしょう。 ### DMI: Random オブジェクトが作成され1度しか使われない (DMI_RANDOM_USED_ONLY_ONCE) このコードは、`java.util.Random` オブジェクトを作成して1つの乱数を生成するために使用して捨てています。 これはあまり良くない品質の乱数を作り出し、効率が悪いです。 できれば、`Random` オブジェクトを1つだけ作成して保存されるようにコードを書き直してください。 そして、毎回新しい乱数は既存の `Random` オブジェクトを呼び出して取得することが必要です。 生成された乱数が推測可能でないことが重要なら、乱数ごとに新しい `Random` オブジェクトを作成してはいけません (値はあまりに簡単に推測可能です)。 その代わりに `java.security.SecureRandom` の使用を強く検討するべきです (そして必要とされる乱数ごとに新しい `SecureRandom` のオブジェクトを作成することを回避します)。 ### DMI: コレクションを消去するために removeAll メソッドを使用しない (DMI_USING_REMOVEALL_TO_CLEAR_COLLECTION) コレクション `c` からすべての要素を除去したいなら、`c.removeAll(c)` ではなく `c.clear` を使用してください。 コレクションを消去するために `c.removeAll(c)` を呼び出すことは、それほど明確ではなく、タイプミスからの誤りに影響されやすく、効率的ではなく、いくつかのコレクションでは、`ConcurrentModificationException` をスローするかもしれません。 ### Dm: System.exit(...) を呼び出しているメソッド (DM_EXIT) `System.exit(...)` を呼び出すことは、Java 仮想マシン全体をシャットダウンさせてしまいます。 それが適切な場合にだけ使用するべきです。 `System.exit(...)` の呼び出しは、他のコードによる呼び出しを困難か不可能にします。 その代わりに RuntimeException をスローすることを検討してください。 ### Dm: 危険なメソッド runFinalizersOnExit を呼び出しているメソッド (DM_RUN_FINALIZERS_ON_EXIT) どんな理由があるにせよ決して `System.runFinalizersOnExit` と `Runtime.runFinalizersOnExit` を呼び出さないでください。 Java ライブラリで最も危険なメソッドの1つです。 -- Joshua Bloch ### ES: String パラメータを == や != を使用して比較している (ES_COMPARING_PARAMETER_STRING_WITH_EQ) このコードは、参照等価性のために == や != を使用して `java.lang.String` パラメータを比較しています。 文字列定数または正準化された文字列だけをメソッドに渡すことを呼び出し元に要求することは必要以上に脆弱で測定可能な性能の向上をもたらしません。 その代わりに `equals(Object)` メソッドを使用することを検討してください。 ### ES: String オブジェクトを == や != を使用して比較している (ES_COMPARING_STRINGS_WITH_EQ) このコードは、参照等価性のために == や != を使用して `java.lang.String` オブジェクトを比較しています。 両方の文字列がソースファイルの定数か、`String.intern()` を使用して正準化されていないかぎり、同じ文字列は2つの異なる String オブジェクトによって表されるかもしれません。 その代わりに `equals(Object)` メソッドを使用することを検討してください。 ### Eq: 抽象クラスは共変な equals メソッドを宣言している (EQ_ABSTRACT_SELF) このクラスは、共変な `equals` メソッドを定義しています。 `java.lang.Object` の `equals` メソッドを正しくオーバーライドするためには `equals` メソッドのパラメータの型は、`java.lang.Object` でなければなりません。 ### Eq: equals メソッドは互換性のないオペランドをチェックしている (EQ_CHECK_FOR_OPERAND_NOT_COMPATIBLE_WITH_THIS) この `equals` メソッドは、引数が互換性のない型 (すなわちスーパタイプでもなく、`equals` メソッドを定義しているクラスのスーパータイプでもサブタイプでもないクラス) なのか確かめています。 たとえば、`Foo` クラスの `equals` メソッドはそのように見えるかもしれません。
>     public boolean equals(Object o) {
>         if (o instanceof Foo)
>             return name.equals(((Foo)o).name);
>         else if (o instanceof String)
>             return name.equals(o);
>         else return false;
>     }
> これは対称的で推移的である `equals` メソッドを実現するのはとても難しいので、バッドプラクティスと見なされています。 プロパティがなければまったく予想していない振る舞いが起こりえます。 ### Eq: compareTo(...) メソッドを定義して Object.equals() を使用しているクラス (EQ_COMPARETO_USE_OBJECT_EQUALS) このクラスは、`compareTo(...)` メソッドを定義していますが、`equals` メソッドは `java.lang.Object` から継承しています。 一般的に`equals` メソッドが true を返す場合に限り、`compareTo` メソッドは0を返すべきです。 これが違反されるなら奇妙で予測できない失敗が PriorityQueue などのクラスで発生します。 J2SE 5.0では、`PriorityQueue.remove()` は `compareTo` メソッドを使用しますが、Java SE 6では、`equals` メソッドを使用します。 Comparable インタフェースの compareTo メソッドの JavaDoc を以下に引用します。 必須というわけではありませんが、`(x.compareTo(y)==0) == (x.equals(y))` であることが強く推奨されます。 一般的に`Comparable` インタフェースを実装しているクラスで、この条件に違反するクラスは明確にこの事実を示す必要があります。 「注:このクラスは `equals` と一貫性のない自然順序付けを持ちます」などと明示することをお勧めします。 ### Eq: equals メソッドはサブタイプのために失敗する (EQ_GETCLASS_AND_CLASS_CONSTANT) このクラスは、サブクラスによる継承によって壊れる `equlas` メソッドがあります。 `equals` メソッドは、クラスリテラルを引数のクラスと比較しています (たとえば、`Foo` クラスで `Foo.class == o.getClass()` のような判定を行っています)。 `this.getClass() == o.getClass()` の方がより良いです。 ### Eq: 共変な equals メソッドの定義 (EQ_SELF_NO_OBJECT) このクラスは、共変な `equals` メソッドを定義しています。 `java.lang.Object` の `equals` メソッドを正しくオーバーライドするためには `equals` メソッドのパラメータの型は、`java.lang.Object` でなければなりません。 ### FI: 空のファイナライザは削除するべき (FI_EMPTY) 空の `finalize` メソッドは役に立たないので削除するべきです。 ### FI: ファイナライザの明示的な呼び出し (FI_EXPLICIT_INVOCATION) このメソッドには明示的にオブジェクトで `finalize` メソッドの呼び出しがあります。 ファイナライザは Java 仮想マシンによって1度だけ実行されることになっているので、これは間違った考えです。 参照によってつながった複数のオブジェクトがファイナライズ可能になると、Java 仮想マシンはすべてのオブジェクトの `finalize` メソッドを呼び出します。 おそらく異なるスレッドで同時にです。 したがって、クラス X の `finalize` メソッドの中から X によって参照されているオブジェクトの `finalize` メソッドを呼び出すのは、とりわけ間違った考えです。 なぜなら、オブジェクトが既に別のスレッドによってファイナライズされているかもしれないからです。 ### FI: ファイナライザはフィールドを null にする (FI_FINALIZER_NULLS_FIELDS) このファイナライザは、フィールドを null にしています。 これは通常誤りでガベージコレクタを助けません。オブジェクトはいずれにしろガベージされます。 ### FI: ファイナライザはフィールドを null にするだけ (FI_FINALIZER_ONLY_NULLS_FIELDS) このファイナライザは、フィールドを null にすること以外に何もしません。 これはまったく無意味であり、オブジェクトがガベージされ、ファイナライズされ、再びガベージされることを要求しています。 `finalize` メソッドを除去するべきです。 ### FI: ファイナライザはスーパークラスのファイナライザを呼び出していない (FI_MISSING_SUPER_CALL) この `finalize` メソッドは、スーパークラスの `finalize` メソッドを呼び出していません。 したがって、スーパークラスのために定義されたどんなファイナライザアクションも実行されません。 `super.finalize()` の呼び出しを追加してください。 ### FI: ファイナライザはスーパークラスのファイナライザを無効にしている (FI_NULLIFY_SUPER) この空の `finalize` メソッドは、明示的にスーパークラスによって定義されたどんなファイナライザの効果も無効にします。 スーパークラスのために定義されたどんなファイナライザアクションも実行されません。 これが意図したことではない場合、メソッドを削除してください。 ### FI: ファイナライザはスーパークラスのファイナライザを呼び出しているだけ (FI_USELESS) この `finalize` メソッドは、スーパークラスの `finalize` メソッドを呼び出しているだけです。 冗長なので削除してください。 ### FS: 書式文字列は \n よりも %n を使用するべき (VA_FORMAT_STRING_USES_NEWLINE) この書式文字列には改行文字 (\n) が含まれています。 一般的に書式文字列には %n を使用することがより望ましいです。%n は、プラットホーム特有の行セパレータを作り出します。 ### GC: 検査されない型への総称呼び出し (GC_UNCHECKED_TYPE_IN_GENERIC_CALL) 総称型パラメータからの特定の型が予想される Object 型をコンパイルするとき、総称型コレクションメソッドへの呼び出しは引数を渡します。 したがって、標準の Java 型システムも静的解析もパラメータとして渡されているオブジェクトが適切な型かどうかに関する有用な情報を提供できません。 ### HE: equals メソッドは定義していますが hashCode メソッドは定義していないクラス (HE_EQUALS_NO_HASHCODE) このクラスは、`equals(Object)` メソッドをオーバーライドしていますが、`hashCode` メソッドはオーバーライドしていません。 したがって、「等価なオブジェクトは等価なハッシュコードを保持する必要がある」という `hashCode` メソッドの汎用規約に違反するかもしれません。 ### HE: equals メソッドを定義して Object.hashCode() を使用しているクラス (HE_EQUALS_USE_HASHCODE) このクラスは、`equals(Object)` をオーバーライドしていますが、`hashCode` メソッドは `java.lang.Object` から継承しています (同一性ハッシュコード (Java 仮想マシンによってオブジェクトに代入された任意の値) を返します)。 したがって、「等価なオブジェクトは等価なハッシュコードを保持する必要がある」という `hashCode` メソッドの汎用規約に違反するかもしれません。 このクラスのインスタンスが HashMap/HashTable に決して代入されるだろうと思わないなら推奨される `hashCode` メソッドの実装は以下のようになります。
>     public int hashCode() {
>         assert false : "hashCodeが呼び出されることは想定されていません。";
>         return 42; // 適当な値
>     }
> ### HE: hashCode メソッドを定義していますが equals メソッドは定義していないクラス (HE_HASHCODE_NO_EQUALS) このクラスは、`hashCode` メソッドを定義していますが、`equals` メソッドは定義していません。 これは「等価なオブジェクトは等価なハッシュコードを保持する必要がある」という `hashCode` メソッドの汎用規約に違反するかもしれません。 ### HE: hashCode メソッドを定義して Object.equals() を使用しているクラス (HE_HASHCODE_USE_OBJECT_EQUALS) このクラスは、`hashCode` メソッドを定義していますが、 `equals` メソッドは `java.lang.Object` から継承しています (オブジェクトの参照比較で等価性を判定します)。 これは「等価なオブジェクトは等価なハッシュコードを保持する必要がある」という `hashCode` メソッドの汎用規約に従っているかもしれませんが、 おそらく、`hashCode` メソッドをオーバーライドすることによって意図されたことではありません。 (`hashCode` メソッドをオーバーライドすることは、オブジェクトの同一性が単純な参照等価性よりも複雑な規約に基づくことを意味します)。 このクラスのインスタンスが HashMap/HashTable に決して代入されるだろうと思わないなら推奨される `hashCode` メソッドの実装は以下のようになります。
>     public int hashCode() {
>         assert false : "hashCodeが呼び出されることは想定されていません。";
>         return 42; // 適当な値
>     }
> ### HE: equals メソッドを継承して Object.hashCode() を使用しているクラス (HE_INHERITS_EQUALS_USE_HASHCODE) このクラスは、抽象スーパークラスから `equals(Object)` メソッドを継承して、`java.lang.Object` から `hashCode` メソッドを継承しています (同一性ハッシュコード (Java 仮想マシンによってオブジェクトに代入された任意の値) を返します)。 したがって、「等価なオブジェクトは等価なハッシュコードを保持する必要がある」という `hashCode` メソッドの汎用規約に違反するかもしれません。 `hashCode` メソッドを定義したくないまたはオブジェクトが HashMap/Hashtable に決して格納されないだろうと思っているなら `UnsupportedOperationException` をスローする `hashCode()` メソッドを定義してください。 ### IC: スーパークラスは初期化中にサブクラスを使用している (IC_SUPERCLASS_USES_SUBCLASS_DURING_INITIALIZATION) クラスは、初期化中にサブクラスを積極的に使用しています。サブクラスはこの時点ではまだ初期化されていません。 たとえば、以下のコードにおいて、`foo` は null です。
>     public class CircularClassInitialization {
>         static class InnerClassSingleton extends CircularClassInitialization {
>             static InnerClassSingleton singleton = new InnerClassSingleton();
>         }

>         static CircularClassInitialization foo = InnerClassSingleton.singleton;
>     }
> ### IMSE: 疑わしい IllegalMonitorStateException のキャッチ (IMSE_DONT_CATCH_IMSE) `IllegalMonitorStateException` は、一般的に設計上の欠陥 (ロックを保持していないオブジェクトで `wait` メソッドまたは `notify` メソッドを呼び出す) の場合にだけスローされます。 ### ISC: static メソッドだけを提供するクラスの不必要なインスタンス化 (ISC_INSTANTIATE_STATIC_CLASS) このクラスは、static メソッドだけを提供するクラスのオブジェクトを作成しています。 このオブジェクトは作成する必要はありません。修飾子として直接クラス名を使用する static メソッドにアクセスしてください。 ### It: Iterator.next() が NoSuchElementException をスローできない (IT_NO_SUCH_ELEMENT) このクラスは、`java.util.Iterator` を実装しています。 しかしながら、`next` メソッドは `java.util.NoSuchElementException` をスローできません。 `next` メソッドは、それ以上要素を返すことができないときは `NoSuchElementException` をスローするように変更するべきです。 ### J2EE: HttpSession への非直列化可能オブジェクトの格納 (J2EE_STORE_OF_NON_SERIALIZABLE_OBJECT_INTO_SESSION) このコードは、HttpSession に非直列化可能オブジェクトを格納していると思われます。 このセッションが不活性化されるか移行したなら、エラーを招きます。 ### JCIP: 不変クラスのフィールドは final にすべき (JCIP_FIELD_ISNT_FINAL_IN_IMMUTABLE_CLASS) クラスは、net.jcip.annotations.Immutable または javax.annotation.concurrent.Immutable でアノテートされています。 アノテーションのルールは、すべてのフィールドが final であることを義務づけます。 ### ME: public 列挙型メソッドが無条件にフィールドを設定するPublic enum method unconditionally sets its field (ME_ENUM_FIELD_SETTER) 無条件に列挙型フィールドを設定している public 列挙型で public メソッドを宣言しています。 したがって、フィールドは悪意のあるコードや偶然別のパッケージによって変更できます。 可変列挙型フィールドが遅延初期化で使用されるかもしれないとしても外界へ暴露するバッドプラクティスです。 このメソッドを除去するかパッケージプライベートとして宣言することを考えてください。 ### ME: 列挙型フィールドは public で可変である (ME_MUTABLE_ENUM_FIELD) 可変 public フィールドが public 列挙型の中に定義されています。 したがって、フィールドは悪意のあるコードや偶然別のパッケージによって変更できます。 可変列挙型フィールドが遅延初期化で使用されるかもしれないとしても外界へ暴露するバッドプラクティスです。 このメソッドを final およびパッケージプライベートとして宣言することを考えてください。 ### NP: 戻り型が Boolean のメソッドが明示的に null を返している (NP_BOOLEAN_RETURN_NULL) Boolean.TRUE、Boolean.FALSE、null を返すメソッドはいつ事故が起きてもおかしくないです。 このメソッドは、まるで論理型の値を返すかのように呼び出されます。 コンパイラは Boolean 値のオートアンボクシングを挿入します。 null 値が返されるなら NullPointerException が発生することになります。 ### NP: null を返すかもしれない clone メソッド (NP_CLONE_COULD_RETURN_NULL) この `clone` メソッドは、いくつかの条件で null を返すと思われます。 しかし、`clone` メソッドは決して null を返すのは許されません。 この経路が到達できないことを確信しているなら、代わりに `AssertionError` をスローしてください。 ### NP: equals メソッドは null の引数をチェックしていない (NP_EQUALS_SHOULD_HANDLE_NULL_ARGUMENT) この `equals(Object)` メソッドの実装は引数として渡されている null をチェックしていないので、`java.lang.Object.equals()` で定義された規約に違反しています。 すべての `equals` メソッドは引数に null が渡されたなら false を返すべきです。 ### NP: null を返すかもしれない toString メソッド (NP_TOSTRING_COULD_RETURN_NULL) この `toString` メソッドは、いくつかの条件で null を返すと思われます。 仕様を寛大に読むとこれが許されると解釈できるかもしれませんが、それはおそらく間違った考えで、他のコードが壊れる原因になる可能性があります。 null ではなく空の文字列または、いくつかの他の適切な文字列を返してください。 ### Nm: クラス名は大文字から始めるべき (NM_CLASS_NAMING_CONVENTION) クラス名は、最初の文字とそれに続く各単語の最初の文字を大文字にした名詞にすべきです。 クラス名は単純でわかりやすいようにしてください。 頭文字や略語 (URLやHTMLなどのように略語がロング形式よりもはるかに広く使われている場合を除く) の使用は避けてください。 ### Nm: 例外クラスのように命名されているが、クラスは Exception から派生されていない (NM_CLASS_NOT_EXCEPTION) このクラスは、例外クラスから派生されていないのにクラス名が「Exception」で終わっています。 これはこのクラスのユーザに紛らわしいです。 ### Nm: 紛らわしい名前のメソッド (NM_CONFUSING) 参照されたメソッドは、大文字の使い方だけによって異なる名前があります。 ### Nm: フィールド名は小文字から始めるべき (NM_FIELD_NAMING_CONVENTION) final でないフィールドの名前は、最初の文字は小文字にし、それに続く各単語の最初の文字を大文字にすべきです。 ### Nm: Java の後のバージョンのキーワードである識別子を使用している (NM_FUTURE_KEYWORD_USED_AS_IDENTIFIER) 識別子は、Java の後のバージョンのキーワードとして予約されている単語です。 コードを Java の後のバージョンでコンパイルするためには変更する必要があります。 ### Nm: Java の後のバージョンのキーワードである識別子を使用している (NM_FUTURE_KEYWORD_USED_AS_MEMBER_IDENTIFIER) この識別子は、Java の後のバージョンのキーワードとして使われます。 このコードと API を参照するどんなコードも、Java の後のバージョンでコンパイルするためには変更する必要があります。 ### Nm: メソッド名は小文字から始めるべきです (NM_METHOD_NAMING_CONVENTION) メソッド名は、最初の文字は小文字にし、それに続く各単語の最初の文字を大文字にした動詞にすべきです。 ### Nm: クラス名は実装されたインタフェースの単純名を遮るべきではない (NM_SAME_SIMPLE_NAME_AS_INTERFACE) このクラスまたはインタフェースは、インタフェースが異なるパッケージであるということを除いて実装された/拡張されたインタフェースと同一の単純名です (たとえば、`alpha.Foo` が `beta.Foo` を継承しているような状況です)。 これは非常に紛らわしく、参照関係を解決するために import 文を見なければならなかったり、スーパークラスのメソッドをオーバーライドしないで誤ってメソッドを定義する状況を作り出します。 ### Nm: クラス名はスーパークラスの単純名を遮るべきではない (NM_SAME_SIMPLE_NAME_AS_SUPERCLASS) このクラスは、スーパークラスが異なるパッケージであるということを除いて、スーパークラスと同一の単純名をです (たとえば、`alpha.Foo` が `beta.Foo` を拡張します)。 これは非常に紛らわしく、参照関係を解決するために import 文を見なければならなかったり、スーパークラスのメソッドをオーバーライドしないで誤ってメソッドを定義する状況を作り出します。 ### Nm: 非常に紛らわしい名前のメソッド (多分意図的) (NM_VERY_CONFUSING_INTENTIONAL) 参照されたメソッドは、大文字の使い方だけによって異なる名前があります。 大文字の使い方が同一ならメソッドの1つが他のメソッドをオーバーライドするので、非常に紛らわしいです。 他のメソッドの存在から、これらのメソッドの両方の存在が意図的で、確実に混乱させていると思われます。 APIの凍結によって両方とも持たざるを得ない場合を除き、それらのうちの1つを除去しようと努力するべきです。 ### Nm: パラメータの間違ったパッケージのためにスーパークラスのメソッドをオーバーライドしていないメソッド (NM_WRONG_PACKAGE_INTENTIONAL) パラメータの型が正確にスーパークラスで対応するパラメータの型と合致していないので、サブクラスのメソッドはスーパークラスの類似したメソッドをオーバーライドしていません。 たとえば以下のようなコードです。
>     import alpha.Foo;

>     public class A {
>         public int f(Foo x) { return 17; }
>     }
>     ----
>     import beta.Foo;

>     public class B extends A {
>         public int f(Foo x) { return 42; }
>         public int f(alpha.Foo x) { return 27; }
>     }
> クラス `B` で定義された `f(Foo)` メソッドは、クラス `A` の `f(Foo)` メソッドをオーバーライドしません。 これは引数の型 `Foo` が違うパッケージだからです。 この場合、サブクラスがスーパークラスのメソッドと同一のシグネチャでメソッドを定義しているので、おそらく理解できます。 しかしながら、そのようなメソッドは非常に紛らわしいです。 類似しているが同一ではないシグネチャのメソッドを除去するか、非推奨にすることを強く検討するべきです。 ### ODR: データベースリソースのクローズに失敗するかもしれないメソッド (ODR_OPEN_DATABASE_RESOURCE) このメソッドは、データベースリソース (たとえば、データベースコネクションや行セット) を作成していますが、どんなフィールドにも代入していないか、他のメソッドにも渡していないか、戻り値にもしていません。 そして、メソッドからのすべての経路でオブジェクトをクローズするように見えません。 メソッドからのすべての経路でデータベースリソースのクローズが失敗すると性能低下になることがあります。 データベースとの通信で問題があるアプリケーションの原因になる可能性があります。 ### ODR: 例外経路でデータベースリソースのクローズに失敗するかもしれないメソッド (ODR_OPEN_DATABASE_RESOURCE_EXCEPTION_PATH) このメソッドは、データベースリソース (たとえば、データベースコネクションや行セット) を作成していますが、どんなフィールドにも代入していないか、他のメソッドにも渡していないか、戻り値にもしていません。 そして、メソッドからのすべての例外経路でオブジェクトをクローズするように見えません。 メソッドからのすべての経路でデータベースリソースのクローズが失敗すると性能低下になることがあります。 データベースとの通信で問題があるアプリケーションの原因になる可能性があります。 ### OS: ストリームのクローズに失敗するかもしれないメソッド (OS_OPEN_STREAM) このメソッドは、入出力ストリームオブジェクトを作成していますが、どんなフィールドにも代入していないしクローズするかもしれない別のメソッドにも渡していなくて、戻り値にしてもいません。そして、メソッドからのすべての経路でクローズするように見えません。 これはファイルディスクリプタリークの原因になることがあります。 ストリームがクローズされることを確実にするために `finally` ブロックを使用することは一般的に良い考えです。 ### OS: 例外経路でストリームのクローズに失敗するかもしれないメソッド (OS_OPEN_STREAM_EXCEPTION_PATH) このメソッドは、入出力ストリームオブジェクトを作成していますが、どんなフィールドにも代入していないしクローズするかもしれない別のメソッドにも渡していないくて、戻り値にしてもいません。そして、メソッドからのすべての可能性がある例外経路でクローズするように見えません。 これはファイルディスクリプターリークの原因になることがあります。 ストリームがクローズされることを確実にするために `finally` ブロックを使用することは一般的に良い考えです。 ### PZ: 繰り返しでエントリオブジェクトを再利用しない (PZ_DONT_REUSE_ENTRY_OBJECTS_IN_ITERATORS) このクラスは、Iterator と Map.Entry で基底 Map のビューを返すことを許可された両方の entrySet メソッドがあります。 この巧妙なアイデアは、Map 実装で使用されましたが、厄介なコーディング間違いの可能性を取り込みました。 Map `m` が entrySet のためのそのような反復子を返すならば、`c.addAll(m.entrySet())` はひどく間違っているでしょう。 OpenJDK 1.7 の すべての Map 実装はこれを回避するために書き直されました。 ### RC: 定数への疑わしい参照比較 (RC_REF_COMPARISON_BAD_PRACTICE) このメソッドは、 参照値を == または != 演算子を使用して定数と比較しています。 一般的にこの型のインスタンスを比較する正しい方法は `equals` メソッドです。 等価で識別可能なインスタンスを作成する可能性がありますが異なるオブジェクトなので == で比較しないでください。 一般的に参照によって比較されるべきではないクラスの例は、`java.lang.Integer` 、`java.lang.Float` などです。 ### RC: Boolean 値の疑わしい参照比較 (RC_REF_COMPARISON_BAD_PRACTICE_BOOLEAN) このメソッドは、== または != 演算子を使用して2つの Boolean 値を比較しています。 一般的には2つの Boolean 値 (`Boolean.TRUE` と `Boolean.FALSE`) だけですが、 `new Boolean(b)` コンストラクタを使用して他の Boolean オブジェクトを作成する可能性があります。 そのようなオブジェクトを回避することは最高です。 しかし、それらが存在するなら、Boolean オブジェクトの等価性をチェックするために `.equals(...)` ではなく == または != を使用しているなら異なる結果をもたらします。 ### RR: InputStream.read() の戻り値を無視しているメソッド (RR_NOT_CHECKED) このメソッドは、複数バイトを返す可能性がある `java.io.InputStream.read()` (またはそのバリエーション) の戻り値を無視しています。 戻り値がチェックされないと呼び出し元は要求したバイト数よりも少ないバイト数を読み出した場合、正しく処理できません。 これは潜在的なバグで、多くのプログラムでは、入力ストリームからの読み出しは、通常要求した完全なデータ量を読み出しますが、散発的に失敗することがあります。 ### RR: InputStream.skip() の戻り値を無視しているメソッド (SR_NOT_CHECKED) このメソッドは、複数バイトをスキップする可能性がある `java.io.InputStream.skip()` の戻り値を無視しています。 戻り値がチェックされないと呼び出し元は要求したバイト数よりも少ないバイト数しかスキップしなかった場合、正しく処理できません。 これは潜在的なバグで、多くのプログラムでは、入力ストリームからのスキップは、通常要求した完全なデータ量をスキップをしますが、散発的に失敗することがあります。 しかしながら、バッファードストリーム での `skip` メソッドはバッファのデータをスキップするので要求されたバイト数のスキップは常に失敗します。 ### RV: compareTo()/compare() の結果を無効にする (RV_NEGATING_RESULT_OF_COMPARETO) このコードは、`compareTo` または `compare` メソッドの戻り値を無効にしています。 これは疑わしいかバッドプログラミングプラクティスです。戻り値が Integer.MIN_VALUE なので、戻り値を無効にすることは結果の符号を無効にしません。 結果を無効にするのではなくオペランドの順序を逆にすることによって、同じ意図した結果を得ることができます。 ### RV: 例外的戻り値を無視しているメソッド (RV_RETURN_VALUE_IGNORED_BAD_PRACTICE) このメソッドはチェックされていない値を返しています。 戻り値は異常か予想外の実行結果を示す可能性があるのでチェックするべきです。 たとえば、`File.delete()` はファイルをうまく削除できなかったなら、例外をスローするのではなく false を返します。 結果をチェックしないなら例外的戻り値を返すメソッドの呼び出しで予想外の振る舞いの合図に気づきません。 ### SI: スタティックイニシャライザは、すべての static final フィールドが代入される前にインスタンスを作成する (SI_INSTANCE_BEFORE_FINALS_ASSIGNED) すべての static final フィールドが初期化される前にスタティックイニシャライザがクラスのインスタンスを作成します。 ### SW: Swing メソッドは AWT イベントディスパッチスレッドから呼び出す必要がある (SW_SWING_METHODS_INVOKED_IN_SWING_THREAD) (From JDC Tech Tip) に解説されているとおり、Swing のメソッド、`show` メソッド、`setVisible` メソッド、`pack` メソッドは、フレームのための関連したピアを作成します。 ピアの作成で、システムはイベントディスパッチスレッドを作成します。 これが問題になることがあります。なぜなら `pack` メソッドと `validate` メソッドがまだ処理中でもイベントディスパッチスレッドがリスナに通知できるからです。 この状況は、2つのスレッドが Swing コンポーネントにアクセスする可能性があり、デッドロックや、その他のスレッドに関する問題になる可能性がある重大な欠陥です。 `pack` メソッドの呼び出しはコンポーネントを実体化させます。実体化しているときに、イベントディスパッチスレッドがリスナへの通知を開始する可能性があります。 ### Se: 直列化可能クラスの非 transient で非直列化可能なインスタンスフィールド (SE_BAD_FIELD) この直列化可能クラスは、transient、Serializable、`java.lang.Object` でもない非プリミティブ型のインスタンスフィールドを定義して、 `Externalizable` インタフェースまたは `readObject` メソッドと `writeObject` メソッドを実装するように見えません。 また、`Externalizable` インタフェースも実装していなくて、`readObject` メソッドも `writeObject` メソッドも定義していません。 非直列化可能オブジェクトがこのフィールドに格納されるならクラスのオブジェクトは正しく直列化復元されません。 ### Se: 非直列化可能クラスに直列化可能な内部クラスがある (SE_BAD_FIELD_INNER_CLASS) この直列化可能クラスは、非直列化可能クラスの内部クラスです。 内部クラスを直列化しようとすると関連する外部クラスのインスタンスを結びつけようとするので、実行時エラーの原因になります。 できれば、内部クラスを static にして問題を解決するべきです。 外部クラスを直列化可能にすることで動作するかもしれないが、内部クラスのインスタンスを直列化することは外部クラスも常に直列化することを意味します。 本当に望むことですか。 ### Se: 非直列化可能な値を直列化可能クラスのインスタンスフィールドに格納している (SE_BAD_FIELD_STORE) 非直列化可能な値を直列化可能クラスの 非 transient フィールドに格納しています。 ### Se: Comparator は Serializable を実装していない (SE_COMPARATOR_SHOULD_BE_SERIALIZABLE) このクラスは `Comparator` インタフェースを実装しています。 `Serializable` インタフェースも実装するべきかどうか検討するべきです。 コンパレータが `TreeMap` のような順序付きコレクションを構築するために使われるなら、コンパレータが直列化可能な場合だけ、`TreeMap` は直列化可能です。 大部分のコンパレータがほとんど状態を持たないとしても直列化可能にすることは簡単で良い防衛的なプログラミングです。 ### Se: 直列化可能な内部クラス (SE_INNER_CLASS) この直列化可能なクラスは内部クラスです。内部クラスを直列化しようとすると関連した外部クラスのインスタンスも直列化します。 外部クラスのインスタンスは直列化可能なので失敗しません。しかし、意図していたよりももっと多くのデータを直列化するかもしれません。 できれば、内部クラスを static にして問題を解決するべきです。 ### Se: serialVersionUID が final ではない (SE_NONFINAL_SERIALVERSIONID) このクラスは、final でない `serialVersionUID` フィールドを定義しています。 直列化を目的としてバージョン UID を指定することを意図しているならフィールドは final とすべきです。 ### Se: serialVersionUID が long ではない (SE_NONLONG_SERIALVERSIONID) このクラスは、long でない `serialVersionUID` フィールドを定義しています。 直列化を目的としてバージョン UID を指定することを意図しているならフィールドは long とすべきです。 ### Se: serialVersionUID が static ではない (SE_NONSTATIC_SERIALVERSIONID) このクラスは、static でない `serialVersionUID` フィールドを定義しています。 直列化を目的としてバージョン UID を指定することを意図しているならフィールドは static とすべきです。 ### Se: Serializable なクラスのスーパークラスで、引数なしコンストラクタを定義していない (SE_NO_SUITABLE_CONSTRUCTOR) このクラスは `Serializable` インタフェースを実装していますが、そのスーパークラスは実装していません。 そのようなオブジェクトが直列化復元されるとき、スーパークラスのフィールドはスーパークラスの引数なしコンストラクタを呼び出すことによって初期化される必要があります。 スーパークラスには引数なしコンストラクタがないので、直列化と直列化復元は実行時に失敗します。 ### Se: Externalizable なクラスが引数なしコンストラクタを定義していない (SE_NO_SUITABLE_CONSTRUCTOR_FOR_EXTERNALIZATION) このクラスは、`Externalizable` インタフェースを実装していますが、引数なしコンストラクタを定義していません。 `Externalizable` オブジェクトが直列化復元されるときは、最初に引数なしコンストラクタを呼び出すことによって構築される必要があります。 このクラスには引数なしコンストラクタがないので、直列化と直列化復元は実行時に失敗します。 ### Se: readResolve メソッドの戻り値の型が Object で宣言されていない (SE_READ_RESOLVE_MUST_RETURN_OBJECT) `readResolve` メソッドが直列化機構で認識されるためには戻り値の型が `Object` で宣言されなければなりません。 ### Se: 直列化復元によって設定されない transient フィールド (SE_TRANSIENT_FIELD_NOT_RESTORED) このクラスには複数の場所で更新されるフィールドがあります。したがって、このクラスの状態の一部だと思われます。 しかしながら、フィールドは transient と宣言しているので、 readObject/readResolve で値が設定されません。 クラスの直列化復元されたインスタンスにはデフォルト値が設定されます。 ### SnVI: Serializable なクラスが serialVersionUID を定義していない (SE_NO_SERIALVERSIONID) このクラスは `Serializable` インタフェースを実装していますが、`serialVersionUID` フィールドを定義していません。 .class オブジェクトへの参照を追加するのと同じくらい簡単な変更でクラスに合成フィールドを追加します。 それは、残念ながら暗黙の `serialVersionUID` を変えます (たとえば、`String.class` への参照を追加すると、`class$java$lang$String` という static フィールドを生成します)。 また、バイトコードコンパイラへの異なるソースコードは、クラスオブジェクトまたは内部クラスを参照するために生成される合成変数のために異なる命名規則を使用するかもしれません。 バージョンを横断する Serializable の相互運用性を保証するために明示的に serialVersionUID を追加することを検討してください。 ### UI: クラスが拡張されるなら getResource の使い方は安全ではないかもしれない (UI_INHERITANCE_UNSAFE_GETRESOURCE) このクラスが別のパッケージによって拡張されるなら、`this.getClass().getResource(...)` の呼び出しは予想外の結果をもたらす可能性があります。 ### BC: 不可能なキャスト (BC_IMPOSSIBLE_CAST) このキャストは、常に ClassCastException をスローします。 FindBugs は、instanceof チェックから型情報を調査して、メソッドからの戻り値とフィールドからロードされた値の型について、より多くの正確な情報を使用します。 したがって、宣言された変数の型にはより多くの正確な情報があるかもしれないしれません。 また、キャストが常に実行時例外をスローするのかを決定するために利用する可能性があります。 ### BC: 不可能なダウンキャスト (BC_IMPOSSIBLE_DOWNCAST) このキャストは、常に ClassCastException をスローします。 解析はキャストしている値の正確な型がわかっていると信じています。 そして、サブタイプへダウンキャストしようとする試みは、ClassCastException のスローによって常に失敗します。 ### BC: toArray メソッドの結果の不可能なダウンキャスト (BC_IMPOSSIBLE_DOWNCAST_OF_TOARRAY) このコードは、以下のように、`Object[]` より特定の型のコレクションで `toArray` メソッドを呼び出す結果をキャストしています。
>     String[] getAsArray(Collection<String> c) {
>       return (String[]) c.toArray();
>     }
> これは通常 ClassCastException をスローして失敗します。 ほとんどすべてのコレクションの `toArray` メソッドは、`Object[]` を返します。 Collection オブジェクトは宣言された総称型コレクションの参照がないので、本当に何もできません。 コレクションから特定の型の配列を得る正しい方法は、`c.toArray(new String[]);` または `c.toArray(new String[c.size()]);` (後者はわずかにより効率的です) を使用することです。 これに対する1つの共通の知られている例外があります。 `Arrays.asList(...)`によって返されるリストの `toArray()` メソッドは共変型配列を返します。 たとえば、`Arrays.asArray(new String[] { "a" }).toArray()` は `String []` を返します。 FindBugs はそのようなケースを検出して抑止しようとしますが、見落としているかもしれません。 ### BC: 常に false を返す instanceof (BC_IMPOSSIBLE_INSTANCEOF) この instanceof は常に false を返します。これは安全で、誤解や論理エラーを指摘していないことを確認してください。 ### BIT: 符号付きバイト値のビット加算 (BIT_ADD_OF_SIGNED_BYTE) バイト値と明らかに下位8ビットがあるとわかっている値を加算しています。 ビット演算を実行する前にバイト配列からロードされた値は32ビットまで符号拡張されます。 したがって、`b[0]` の値が `0xff` で、`x` の初期値が `0` だとすると、 `((x << 8) + b[0])` は、`0xff` が符号拡張で `0xffffffff` になるので、結果として `0xffffffff` が得られます。 特に、バイト配列 int にパックする以下のようなコードはひどく間違っています。
>     int result = 0;
>     for(int i = 0; i < 4; i++)
>       result = ((result << 8) + b[i]);
> その代わりに以下のようなイディオムは動作します。
>     int result = 0;
>     for(int i = 0; i < 4; i++)
>       result = ((result << 8) + (b[i] & 0xff));
> ### BIT: 互換性のないビットマスク (BIT_AND) このメソッドは、(e & C) 形式の式を D と比較しています。 定数 C の特定の値と D ために常に等しくないことを比較します。論理エラーかタイプミスかもしれません。 ### BIT: ((...) & 0) == 0 なのか確かめている (BIT_AND_ZZ) このメソッドは、(e & 0) 形式の式を0と比較しています。それは、常に等価であることを比較します。論理エラーかタイプミスかもしれません。 ### BIT: 互換性のないビットマスク (BIT_IOR) このメソッドは、`(e | C)` 形式の式を `D` と比較しています。 定数 C の特定の値と D のために常に等しくないことを比較します。論理エラーかタイプミスかもしれません。 典型的に、このバグは、ビットセットで帰属関係のテストを実行したいコードで発生します。 しかし、ビット論理積演算子 ("&") の代わりにビット論理和演算子 ("|") を使用しています。 ### BIT: 符号付きバイト値のビット論理和 (BIT_IOR_OF_SIGNED_BYTE) ロードしたバイト値 (たとえば、バイト配列からロードされた値や戻り値がバイト型のメソッドから返された値) とビット論理和を実行しています。 ビット演算を実行する前にバイト値は32ビットまで符号拡張されます。 したがって、`b[0]` の値が `0xff` で、`x` の初期値が `0` だとすると、 `((x << 8) | b[0])` は、`0xff` が符号拡張で `0xffffffff` になるので、結果として `0xffffffff` が得られます。 特に、バイト配列 int にパックする以下のようなコードはひどく間違っています。
>     int result = 0;
>     for(int i = 0; i < 4; i++) {
>         result = ((result << 8) | b[i]);
>     }
> その代わりに以下のようなイディオムは動作します。
>     int result = 0;
>     for(int i = 0; i < 4; i++) {
>         result = ((result << 8) | (b[i] & 0xff));
>     }
> ### BIT: ビット演算の符号をチェックする (BIT_SIGNED_CHECK_HIGH_BIT) このメソッドは、`((event.detail & SWT.SELECTED) > 0)` のような式を比較しています。 ビット演算をより大きい演算子で比較することは、予想外の結果 (もちろん、`SWT.SELECTED` の値による) の原因になる可能性があります。 `SWT.SELECTED` が負数であるなら、これはバグの候補です。 `SWT.SELECTED` が負ではないとしても、'> 0' の代わりに '!= 0' を使用することは良いプラクティスと思われます。 Boris Bokowski ### BOA: スーパークラスの Adapter で実装されるメソッドを誤ってオーバーライドしているクラス (BOA_BADLY_OVERRIDDEN_ADAPTER) このメソッドは、スーパークラスで実装されているメソッドをオーバーライドしています。 スーパークラスは、java.awt.event や javax.swing.event パッケージで定義されているリスナを実装する Adapter です。 その結果、イベントが発生するときこのメソッドは呼び出されません。 ### BSHIFT: シフト演算の正しくない構文解析の可能性がある (BSHIFT_WRONG_ADD_PRIORITY) コードは (x << 8 + y) のような操作を行います。 これは正しいかもしれませんが、おそらく (x << 8) + y を行うことを意図していました。 しかし、シフト演算は優先順位が低いので、実際には x << (8 + y) として構文解析されます。 ### BSHIFT: 32ビット int の-31から31の範囲を超えた量によるシフト (ICAST_BAD_SHIFT_AMOUNT) このコードは、32ビット int の-31から31の範囲を超えた量でシフトを実行しています。 これの効果は、どのくらいシフトするのかを決めるために整数値の下位5ビット (32で割った余り) を使用することです (たとえば、40ビットでシフトすることは8ビットでシフトすることと同じで、32ビットでシフトすることは0ビットでシフトすることと同じです)。 これはおそらく期待されたことではなく、少なくとも紛らわしいです。 ### DLS: return 文に無駄なインクリメントがある (DLS_DEAD_LOCAL_INCREMENT_IN_RETURN) `return x++;` のような return 文があります。 接頭辞インクリメント/デクリメントは 式の値に影響を与えないので、インクリメント/デクリメントは効果がありません。 この文が正しいのか確かめてください。 ### DLS: クラスリテラルの無効な代入 (DLS_DEAD_STORE_OF_CLASS_LITERAL) この命令は変数にクラスリテラルを代入していますが、決して使われません。 The behavior of this differs in Java 1.4 and in Java 5 J2SE 1.4 およびそれ以前のバージョンでは、`Foo.class` への参照は `Foo` のためのスタティックイニシャライザが既に実行されていないなら実行することを強制します。 J2SE 5.0 ではそうしません。 より多くの詳細と例と J2SE 5.0 のクラスの強制的な初期化の方法の提案は Sun の article on Java SE compatibility を参照してください。 ### DLS: 上書きされたインクリメント (DLS_OVERWRITTEN_INCREMENT) このコードは、インクリメント演算 (たとえば、`i++`) を実行してすぐに上書きしています。 たとえば、`i = i++` は元の値をインクリメントした値で上書きします。 ### DMI: 逆にされた引数 (DMI_ARGUMENTS_WRONG_ORDER) このメソッド呼び出しへの引数は、順序が間違っているように見えます。 たとえば、呼び出し `Preconditions.checkNotNull("message", message)` は、引数を予約しました。チェックされる値は第一引数です。 ### DMI: 月のための間違った定数値 (DMI_BAD_MONTH) このコードは、メソッドに0から11の範囲外の月定数値を渡しています。 ### DMI: 正確に表されない double から構築された BigDecimal (DMI_BIGDECIMAL_CONSTRUCTED_FROM_DOUBLE) このコードは、10進数の数にうまく変換されない double 値から BigDecimal を作成しています。 たとえば、Java で `new BigDecimal(0.1)` と書くと、0.1と正確に等しい BigDecimal (スケールが1でスケールなしの値が1) が作成されると思うかもしれませんが、 実際には0.1000000000000000055511151231257827021181583404541015625と等しくなります。 おそらく `BigDecimal.valueOf(double d)` メソッドの使用が望ましいです。BigDecimal(たとえば、`BigDecimal.valueOf(0.1)` は0.1を与えます) を作成するためには double の文字列表現を使用します。 ### DMI: hasNext メソッドで next メソッドを呼び出している (DMI_CALLING_NEXT_FROM_HASNEXT) `hasNext` メソッドは、`next` メソッドを呼び出しています。 `hasNext` メソッドは、イテレータの状態を変更することになっていないので、ほぼ確実に間違っています。 `next` メソッドがイテレータの状態を変更することになっています。 ### DMI: コレクションは自分自身を含めるべきではない (DMI_COLLECTIONS_SHOULD_NOT_CONTAIN_THEMSELVES) この総称型コレクションメソッドへの呼び出しはコレクションに自分自身が含まれている場合 (たとえば、`s.contains(s)` が true) にだけ意味があります。 これが本当だとは思えないし、もし本当なら問題の原因になります (たとえば、無限再帰になっているハッシュコードの計算)。 間違ったパラメータが渡されている可能性が高いです。 ### DMI: D'oh! 無意味なメソッド呼び出し (DMI_DOH) この部分的なメソッド呼び出しは、検査から明らかな理由で意味がありません。 ### DMI: 配列で hashCode メソッドを呼び出している (DMI_INVOKING_HASHCODE_ON_ARRAY) このコードは、配列で `hashCode` メソッドを呼び出しています。 配列で `hashCode` メソッドを呼び出すことは、System.identityHashCode と同じ値を返すので、コンテンツと配列の長さを無視します。 配列 `a` のコンテンツによるハッシュコードを必要とするなら、`java.util.Arrays.hashCode(a)` を使用してください。 ### DMI: int に対して Double.longBitsToDouble() を呼び出している (DMI_LONG_BITS_TO_DOUBLE_INVOKED_ON_INT) `Double.longBitsToDouble()` の呼び出しで、32ビット int 値が引数として渡されています。 これはほぼ間違いなく意図したことではありませんし意図した結果を与えることはほとんどありません。 ### DMI: コレクションへの無意味な呼び出し (DMI_VACUOUS_SELF_COLLECTION_CALL) この呼び出しは意味がありません。 どんなコレクション `c` も `c.containsAll(c)` を呼び出すことは常に true であるべきです。 そして、`c.retainAll(c)` は効果があるはずがありません。 ### Dm: ランタイムリテンションなしで、アノテーションの存在を調べるためにリフレクションを使用することはできない (DMI_ANNOTATION_IS_NOT_VISIBLE_TO_REFLECTION) アノテーションは、`@Retention(RetentionPolicy.RUNTIME)` でアノテートされなければ、リフレクション (たとえば、`isAnnotationPresent(...)` メソッド) を使用して観測することができません。 ### Dm: ScheduledThreadPoolExecutor の最大プールサイズを変えようとする無駄な試み (DMI_FUTILE_ATTEMPT_TO_CHANGE_MAXPOOL_SIZE_OF_SCHEDULED_THREAD_POOL_EXECUTOR) `ScheduledThreadPoolExecutor` は `ThreadPoolExecutor` から継承されますが継承されたチューニングメソッドの一部は有用ではありません。 特に、corePoolSize スレッドとアンバウンド形式のキューを使用する固定サイズプールとして動作するので、maximumPoolSize の調整は有用な効果がありません。 (Javadoc) ### Dm: コアプールサイズが0の ScheduledThreadPoolExecutor の作成 (DMI_SCHEDULED_THREAD_POOL_EXECUTOR_WITH_ZERO_CORE_THREADS) コアプールサイズが0の `ScheduledThreadPoolExecutor` は決して何も実行しません。 最大プールサイズへの変更は無視されます。 (Javadoc) ### Dm: EasyMock メソッドへの役に立たない/無意味な呼び出し (DMI_VACUOUS_CALL_TO_EASYMOCK_METHOD) この呼び出しは EasyMock メソッドにどんなオブジェクトも渡さないので何もしません。 ### Dm: Math.max と Math.min の間違った組み合わせ (DM_INVALID_MIN_MAX) このコードは、`Math.min(0, Math.max(100, value))` のような構文を使用して境界値を制限しようとしています。 しかしながら、定数の順序が間違っています。 `Math.min(100, Math.max(0, value))` とすべきです。 結果としてこのコードは常に同じ結果 （もし値が NaN なら NaN） を作り出します。 ### EC: equals メソッドを使用して配列と非配列を比較している (EC_ARRAY_AND_NONARRAY) このメソッドは、配列と配列だと思われない参照を比較するために `.equals(Object o)` を呼び出しています。 比較されているものが違う型なら等しくないことであることが保証されているので、比較はほぼ間違いなく誤りです。 たとえそれらが両方とも配列だったとしても、配列の `equals` メソッドは2つの配列が同じオブジェクトだと決定するだけです。 配列のコンテンツを比較するためには `java.util.Arrays.equals(Object[], Object[])` を使用してください。 ### EC: 配列の equals メソッド呼び出しは == と等価である (EC_BAD_ARRAY_COMPARE) このメソッドは、配列で `.equals(Object o)` を呼び出しています。 配列は、`Object` の `equals` メソッドをオーバーライドしないので、配列で `equals` メソッドを呼び出すことはアドレスを比較することと同じです。 配列のコンテンツを比較するためには `java.util.Arrays.equals(Object[], Object[])` を使用してください。 配列のアドレスを比較するために明示的に `==` を使用して参照等価性をチェックすることは、それほど紛らわしくないでしょう。 ### EC: equals(...) メソッドを使用して互換性のない配列を比較している (EC_INCOMPATIBLE_ARRAY_COMPARE) このメソッドは、互換性のない型の配列を比較するために `.equals(Object o)` を呼び出しています (たとえば、`String[]` と `StringBuffer[]`、`String[]` と `int[]`) 。 それらは、決して等価ではありません。 さらに、`equals(...)` が配列を比較するのに使用されるとき、それらが同じ配列であるかどうか確かめるだけで、配列のコンテンツは無視します。 ### EC: equals(null) の呼び出し (EC_NULL_ARG) このメソッドは、 null 値の引数を渡して `equals(Object)` を呼び出しています。 `equals` メソッドの規約によると、この呼び出しは常に false を返すはずです。 ### EC: equals メソッドを呼び出して無関係のクラスとインタフェースを比較している (EC_UNRELATED_CLASS_AND_INTERFACE) このメソッドは、一方がクラスで他方がインタフェースである2つの参照で `equals(Object)` メソッドを呼び出しています。 クラスは、そのクラスの非抽象サブクラスも含めてインタフェースを実装していません。 したがって比較されている2つのオブジェクトは実行時に同じクラスのメンバである可能性が低いです (いくつかのアプリケーションクラスが解析できなかったか、動的クラスローディングが実行時に起こることができた場合を除く)。 `equals` メソッドの規約によると、異なるクラスのオブジェクトは常に等しくないとして比較するべきです。 したがって、`java.lang.Object.equals(Object)` によって定義される規約によれば、この比較の結果は実行時に常に false になります。 ### EC: equals メソッドを呼び出して異なる型のインタフェースを比較している (EC_UNRELATED_INTERFACES) このメソッドは、どちらも他方のサブタイプでない無関係なインタフェース型の2つの参照で `equals(Object)` メソッドを呼び出しています。 そして、両方のインタフェースを実装する既知の非抽象クラスがありません。 したがって比較されている2つのオブジェクトは実行時に同じクラスのメンバである可能性が低いです (いくつかのアプリケーションクラスが解析できなかったか、動的クラスローディングが実行時に起こることができた場合を除く)。 `equals` メソッドの規約によると、異なるクラスのオブジェクトは常に等しくないとして比較するべきです。 したがって、`java.lang.Object.equals(Object)` によって定義される規約によれば、この比較の結果は実行時に常に false になります。 ### EC: equals メソッドを呼び出して異なる型を比較している (EC_UNRELATED_TYPES) このメソッドは、異なるクラス型の2つの参照で `equals(Object)` メソッドを呼び出していて、解析が実行時に異なるクラスのオブジェクトになることを示唆しています。 さらに、呼び出されるであろう　equals メソッドの検査では、この呼び出しは常に false を返すか、 あるいは equals メソッドが対称 (Object クラスの equals のための契約に必要な性質) ではないことのどちらかを示唆しています。 ### EC: 参照等価性を使用して異なる型を比較している (EC_UNRELATED_TYPES_USING_POINTER_EQUALITY) このメソッドは異なる型と思われる2つの参照を比較するために参照等価性を使用しています。 この比較の結果は、常に false です。 ### Eq: equals メソッドは常に false を戻す (EQ_ALWAYS_FALSE) このクラスでは、常に false を返す `equlas` メソッドを定義しています。 これはオブジェクトがそれ自身と等価ではないことを意味していて、このクラスの有用な Map や Set を作成できません。 より根本的に、`equals` メソッドの要件の一つである反射性を満たしていないことになります。 おそらく意図されたことは、オブジェクトはそれ自身と等価であるというオブジェクト同一性です。 これは `Object` クラスから継承される振る舞いです。 異なるスーパークラスから継承される `equals` メソッドをオーバーライドする必要があるなら以下のようなコードが使えます。
>     public boolean equals(Object o) {
>         return this == o;
>     }
> ### Eq: equals メソッドは常に true を返す (EQ_ALWAYS_TRUE) このクラスは、常に true を返す `equals` メソッドを定義しています。 これは想像力に富むが、あまり良い方法とはいえません。さらに、`equals` メソッドが対称的ではないことを意味します。 ### Eq: equals メソッドはクラスオブジェクトではなくクラス名を比較している (EQ_COMPARING_CLASS_NAMES) このメソッドは、クラス名を比較することによって、2つのオブジェクトが同じクラスなのか確かめています。 異なるクラスローダによってロードされたクラスなら、同じ名前で異なるクラスがある可能性があります。 クラスオブジェクトが同じなのか確かめてください。 ### Eq: 列挙型は共変な equals メソッドを定義している (EQ_DONT_DEFINE_EQUALS_FOR_ENUM) このクラスは列挙を定義していて、列挙の等価性はオブジェクト同一性を使用して定義されています。 列挙値のために共変な `equals` メソッドを定義することは、ひどいバッドプラクティスです。 2つの異なる列挙値が `equals` メソッドでは「等価ではない」と判定され、共変な `equals` メソッドでは「等価」と判定されるからです。 共変な `equals` メソッドを定義しないでください。 ### Eq: equals(Object) メソッドをオーバーライドしていない equals メソッドの定義 (EQ_OTHER_NO_OBJECT) このクラスは、`equals` メソッドを定義していますが、`java.lang.Object` クラスの `equals(Object)` メソッドをオーバーライドしていません。 その代わりに、スーパークラスから `equals(Object)` メソッドを継承して、`boolean equals(Object)` メソッドを定義するべきです。 ### Eq: Object.equals(Object) をオーバーライドしていない equals メソッドの定義 (EQ_OTHER_USE_OBJECT) このクラスは、`equals` メソッドを定義していますが、`java.lang.Object` クラスの `equals(Object)` メソッドをオーバーライドしていません。 クラスは、`boolean equals(Object)` メソッドを定義するべきです。 ### Eq: equals メソッドはスーパークラスの equals メソッドをオーバーライドしているが、対称的ではないかもしれない (EQ_OVERRIDING_EQUALS_NOT_SYMMETRIC) このクラスはスーパークラスの `equals` メソッドをオーバーライドする `equals` メソッドを定義しています。 両方の `equals` メソッドは、2つのオブジェクトが等しいかどうかの判定で、`instanceof` を使用しています。 `equals` メソッドは対称的 (`a.equals(b) == b.equals(a)`) であることが重要なのでこれは危険を伴っています。 B が A のサブタイプなら A の `equals` メソッドは引数が `instanceof A` なのかチェックします。 そして、B の `equals` メソッドは引数が `instanceof B` なのかチェックします。 これらのメソッドによって定義された同値関係が対称的でないということです。 ### Eq: 共変な equals メソッドを定義して、Object.equals(Object) を継承している (EQ_SELF_USE_OBJECT) このクラスは、共変な `equals` メソッドを定義していますが、 `equals(Object)` メソッドは `java.lang.Object` クラスから継承しています。 クラスは、`boolean equals(Object)` メソッドを定義するべきです。 ### FE: NaN への等価性のための絶望的なテスト (FE_TEST_IF_EQUAL_TO_NOT_A_NUMBER) このコードは、浮動小数点が特別な非数値と等価であるか確かめています (たとえば `if (x == Double.NaN)`)。 しかしながら、`NaN` の特別な意味のため、値は `NaN` と等価ではありません。 したがって、`x == Double.NaN` は常に false と評価します。 `x` という値が特別な非数値であるかどうか確かめるためには `Double.isNaN(x)` を使用します (または `x` が浮動小数点精度であるなら `Float.isNaN(x)`)。 ### FS: 書式指示子へ渡している引数に互換性がない (VA_FORMAT_STRING_BAD_ARGUMENT) 書式指示子は、対応する引数と互換性がありません。 たとえば、`System.out.println("%d\n", "hello");` の %d 書式指示子は数値の引数を必要としますが数値ではなく文字列が渡されています。 この文が実行されると実行時例外が発生します。 ### FS: 与えられた引数の型は書式指示子に合致しません (VA_FORMAT_STRING_BAD_CONVERSION) 引数の1つは、対応する書式指示子と互換性がありません。その結果、実行されるときに実行時例外を生成します。 たとえば、`String.format("%d", "1")` は、文字列 "1" が書式指示子 "%d" と互換性がないので例外を生成します。 ### FS: printf スタイルの書式が期待されているところで MessageFormat が与えられている (VA_FORMAT_STRING_EXPECTED_MESSAGE_FORMAT_SUPPLIED) Java の printf 書式文字列と引数のリストを期待するメソッドが呼び出されています。 しかしながら、書式文字列にはどんな書式指示子 (たとえば、%s) も含まないで、メッセージフォーマットの要素 (たとえば、{0}) を含んでいます。 printf スタイルの書式文字列が必要なときに、MessageFormat の文字列を与えている可能性が高いです。 実行時に、すべての引数は無視され、書式文字列は正確にフォーマットされずに返されます。 ### FS: 書式文字列で実際に使われるより、多くの引数が渡されている (VA_FORMAT_STRING_EXTRA_ARGUMENTS_PASSED) 可変長引数による書式文字列メソッドが呼び出されていますが書式文字列で実際に使われるより多くの引数が渡されています。 これは実行時例外の原因とはなりませんが、コードはフォーマットされた文字列に含まれることを意図した情報を黙って省略しているかもしれません。 ### FS: 無効な書式文字列 (VA_FORMAT_STRING_ILLEGAL) 書式文字列は構文的に無効です。この文が実行されると実行時例外が発生します。 ### FS: 書式文字列は足りない引数を参照している (VA_FORMAT_STRING_MISSING_ARGUMENT) 書式文字列で書式指示子を満たすために十分な引数が渡されていません。この文が実行されると実行時例外が発生します。 ### FS: 書式文字列ための前の引数がない (VA_FORMAT_STRING_NO_PREVIOUS_ARGUMENT) この書式文字列は、前の書式指示子の引数が再利用されるようにするために「相対インデックス ("<")」を指定しています。 しかしながら、前の引数がありません。 たとえば、`formatter.format("%<s %s", "a", "b")` が実行されると MissingFormatArgumentException をスローします。 ### GC: 型パラメータとメソッド引数に関係がない (GC_UNRELATED_TYPES) 総称型コレクションメソッドへの呼び出しにコレクションのパラメータとは互換性のないクラスの引数があります (すなわち、引数の型は総称型引数に対応するスーパタイプでもサブタイプでもありません)。 したがって、コレクションにはここで使用されたメソッド引数と等価であるどんなオブジェクトも含まれていません。 多分間違った値がメソッドに渡されています。 一般的に2つの無関係なクラスのインスタンスは等価ではありません。 たとえば、`Foo` と `Bar` クラスがサブタイプによって関係がないなら、`Foo` のインスタンスは `Bar` のインスタンスと等価のはずがありません。 その他の問題で対称的ではない `equals` メソッドになる可能性が高いです。 たとえば、`Foo` が `String` と等価であるように `Foo` クラスを定義するなら、`String` は `String` だけと等価であるので、`equals` メソッドは対称的ではありません。 まれに、非対称 `equals` メソッドを定義して、まだ、何とかそれらのコードを機能させています。 APIのどれも文書化していないか、保証もしていないが、`Collection<String>` に `Foo` があるかどうか調べたいなら、 引数の `equals` メソッド (たとえば、`Foo`クラスの `equals` メソッド) を使用して等価性をチェックします。 ### HE: ハッシュ化された文脈でハッシュ化できないクラスの使用がシグネチャで宣言されている (HE_SIGNATURE_DECLARES_HASHING_OF_UNHASHABLE_CLASS) メソッド、フィールド、クラスは、ハッシュ可能なクラスが必要な文脈で、ハッシュ化できないクラスが使用される総称的なシグネチャを宣言しています。 クラスは、`equals` メソッドを宣言していますが、`hashCode` メソッドは `java.lang.Object` から継承しています。 これは「等価なオブジェクトは等価なハッシュコードを保持する必要がある」という `hashCode` メソッドの汎用規約に従っていないのでハッシュ化できません。 ### HE: ハッシュデータ構造で hashCode メソッドのないクラスを使用している (HE_USE_OF_UNHASHABLE_CLASS) このクラスは、`equals(Object)` メソッドを定義していますが、`hashCode` メソッドを定義していません。 これは「等価なオブジェクトは等価なハッシュコードを保持する必要がある」という `hashCode` メソッドの汎用規約に従っていません。 このクラスのインスタンスはハッシュデータ構造で使われています。最重要問題を修正する必要があります。 ### ICAST: int 値を long に変換して絶対時間として使用している (ICAST_INT_2_LONG_AS_INSTANT) このコードは、32ビット int 値を64ビット long 値に変換して、絶対時間値を必要とするメソッドパラメータに渡しています。 絶対時間値は、「エポック」（すなわち、1970年1月1日、00:00:00 GMT）としてわかっている標準的な基準時間からのミリ秒数です。 たとえば、次のメソッド （エポックからの秒を Date へ変換することを意図した） はひどく壊れています。
>     Date getDate(int seconds) { return new Date(seconds * 1000); }
> 乗算は32ビット演算を使用して、64ビット値に変換されます。 32ビット値は、64ビットに変換されて、絶対時間値を表すために使用されるとき、1969年12月と1970年1月の日付しか表せません。 上記のメソッドの正しい実装は以下のとおりです。
>     // 失敗、2037年後の日付
>     Date getDate(int seconds) { return new Date(seconds * 1000L); }

>     // より良い、すべての日付で動作する
>     Date getDate(long seconds) { return new Date(seconds * 1000); }
> ### ICAST: 整数値を double にキャストして Math.ceil() に渡している (ICAST_INT_CAST_TO_DOUBLE_PASSED_TO_CEIL) このコードは、整数値 (たとえば、int や long) を倍精度浮動小数点に変換してから、その結果を `Math.ceil()` に渡しています。 整数を double に変換すると小数部がない数値が得られるので、この演算は常にノーオペレーションになります。 `Math.ceil()`に渡される値を生成した演算が倍精度浮動小数点演算を使用して実行することを意図した可能性が高いです。 ### ICAST: 整数値を float にキャストして Math.round() に渡している (ICAST_INT_CAST_TO_FLOAT_PASSED_TO_ROUND) このコードは、整数値を float 精度浮動小数点に変換してから、その結果を `Math.round()` に渡して引数に最も近い int/long を返します。 整数を float に変換すると小数部がない数値が得られるので、この演算は常にノーオペレーションになります。 `Math.round()`に渡される値を生成した演算が浮動小数点演算を使用して実行することを意図した可能性が高いです。 ### IJU: run メソッドでの JUnit アサーションは JUnit によって通知されない (IJU_ASSERT_METHOD_INVOKED_FROM_RUN_METHOD) `run` メソッドで JUnit アサーションが実行されています。失敗した JUnit アサーションは例外をスローします。 したがって、この例外がテストメソッドを実行したスレッド以外のスレッドで発生するなら、例外はスレッドを終了させますが、テストの失敗になりません。 ### IJU: TestCase は suite メソッドの間違った宣言をしている (IJU_BAD_SUITE_METHOD) JUnit の TestCase クラスで、`suite` メソッドを実装しています。 しかしながら、`suite` メソッドは、
>     public static junit.framework.Test suite()
> か
>     public static junit.framework.TestSuite suite()
> のどちらかを宣言する必要があります。 ### IJU: TestCase はテストがない (IJU_NO_TESTS) JUnit の TestCase クラスで、どんなテストメソッドも実装していません。 ### IJU: TestCase は super.setup() を呼び出さない setUp メソッドを実装している (IJU_SETUP_NO_SUPER) JUnit の TestCase クラスで、`setUp` メソッドを実装しています。 `setUp` メソッドは、`super.setUp()` を呼び出すべきなのにそうしていません。 ### IJU: TestCase は 非 static な suite メソッドを実装している (IJU_SUITE_NOT_STATIC) JUnit の TestCase クラスで、`suite` メソッドを実装しています。 `suite` メソッドは static として宣言するべきなのにそうしていません。 ### IJU: TestCase は super.tearDown() を呼び出さない tearDown メソッドを実装している (IJU_TEARDOWN_NO_SUPER) JUnit の TestCase クラスで、`tearDown` メソッドを実装しています。 `tearDown` メソッドは、`super.tearDown()` を呼び出すべきなのにそうしていません。 ### IL: コレクションは自分自身を追加している (IL_CONTAINER_ADDED_TO_ITSELF) コレクションは、自分自身を追加しています。その結果、hashCode を計算すると `StackOverflowException` をスローします。 ### IL: 明らかな無限ループ (IL_INFINITE_LOOP) このループは、例外をスローする以外の方法で終了させることができないように思われます。 ### IL: 明らかな無限再帰ループ (IL_INFINITE_RECURSIVE_LOOP) このメソッドは、無条件で自分自身を呼び出します。これはスタックオーバーフローになる無限再帰ループを示しています。 ### IM: 整数剰余の結果の整数乗算 (IM_MULTIPLYING_RESULT_OF_IREM) このコードは、整数剰余の結果に整数定数を乗算しています。 紛らわしい演算子の優先順位がないことを確実にしてください。 たとえば、i % 60 * 1000 は、i % (60 * 1000) ではなく (i % 60) * 1000 となります。 ### INT: int 値と long 定数との間違った比較 (INT_BAD_COMPARISON_WITH_INT_VALUE) このコードは、int 値と int 値として表される値の範囲外の long 定数を比較しています。 この比較は無意味で、おそらく間違っています。 ### INT: 負でない値と負の定数またはゼロとの間違った比較 (INT_BAD_COMPARISON_WITH_NONNEGATIVE_VALUE) このコードは、負でないことが保証されている値と負の定数またはゼロとを比較しています。 ### INT: 符号付きバイトの間違った比較 (INT_BAD_COMPARISON_WITH_SIGNED_BYTE) 符号付バイトのとりうる値の範囲は-128～127です。その範囲外で符号付バイトを値と比較することは無意味で間違っていそうです。 符号付きバイト `b` を範囲が0～255の符号なしバイトに変換するには `0xff & b` を使用してください。 ### IO: オブジェクト出力ストリームへの追加は失敗に終わる (IO_APPENDING_TO_OBJECT_OUTPUT_STREAM) このコードは、ファイルを追加モードで開いて、オブジェクト出力ストリームの中で結果をラップしています。 これはファイルに格納された既存のオブジェクト出力ストリームに追加できないでしょう。 オブジェクト出力ストリームに追加したいなら、オブジェクト出力ストリームを開いておく必要があります。 追加モードでファイルを開き、オブジェクト出力ストリームで書き込むことができる唯一の状況は、 ファイルを読み出すときにランダムアクセスモードで開き、追加を開始するところまでバイトオフセットをシークすると計画した場合です。 ### IP: メソッドで読み取られずに上書きされているパラメータ (IP_PARAMETER_IS_DEAD_BUT_OVERWRITTEN) このパラメータの初期値は無視され、ここで上書きされています。 これは多くの場合、パラメータへの書き込みが呼び出し元に戻されるという誤った考えを示しています。 ### MF: スーパークラスのフィールドを隠すフィールドを定義しているクラス (MF_CLASS_MASKS_FIELD) このクラスは、スーパークラスの可視インスタンスフィールドと同じ名前でフィールドを定義しています。 これは紛らわしくて、メソッドがフィールドを更新するかアクセスするなら、間違いを指摘するかもしれません。 ### MF: フィールドを隠す変数を定義しているメソッド (MF_METHOD_MASKS_FIELD) このメソッドは、このクラスまたはスーパークラスのフィールドと同じ名前でローカル変数を定義しています。 フィールドから初期化されていない値を読み出す、初期化されていないフィールドをそのままにしておくか、または両方を引き起こすかもしれません。 ### NP: null 値を利用している (NP_ALWAYS_NULL) ここで null 値を利用しようとしています。 コードが実行されると NullPointerException が発生します。 ### NP: null 値を例外経路で利用している (NP_ALWAYS_NULL_EXCEPTION) 例外経路上のここで null 値を利用しています。コードが実行されると NullPointerException が発生します。 現在の FindBugs は実行不可能な例外経路を刈り取れていないので、誤検出かもしれないことに注意してください。 switch 文の default が多くの場合実行不可能なので FindBugs が例外経路である default を検討することに注意して下さい。 ### NP: null の引数をチェックしていないメソッド (NP_ARGUMENT_MIGHT_BE_NULL) このメソッドへのパラメータが null かどうか確かめるために常にチェックされるべき値として特定されました。 しかし、null チェックをしないで、null 値が利用されています。 ### NP: 常に null 値のオブジェクトで close メソッドを呼び出している (NP_CLOSING_NULL) `close` メソッドは、常に null 値のオブジェクトで呼び出されています。 この文が実行されるなら NullPointerException が発生します。 ここでクローズするべき何かを決してクローズしないという大きな危険性があります。 ### NP: null 値を利用することが保証されている (NP_GUARANTEED_DEREF) 文または分岐が実行されるなら、この時点で値は null であり、null 値を利用する (フォワードパスで実行時例外を伴うこと以外は) ことが保証されています。 なお、`if (x == null) throw new NullPointerException();` は `x` の参照解除として扱われることに注意して下さい。 ### NP: null 値を例外経路で利用することが保証されている (NP_GUARANTEED_DEREF_ON_EXCEPTION_PATH) 例外経路上の文または分岐が実行されるなら、この時点で値は null であり、null 値を利用する (フォワードパスで実行時例外を伴うこと以外は) ことが保証されています。 ### NP: 非 null フィールドは初期化されていない (NP_NONNULL_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR) フィールドは、非 null としてマークされていますが、コンストラクタで書き込まれていません。 フィールドは、コンストラクタの間、ほかの場所で初期化されるか、または使用する前に常に初期化されるかもしれません。 ### NP: メソッド呼び出しは非 null パラメータに対して null を渡している (NP_NONNULL_PARAM_VIOLATION) このメソッドは、非 null でなければならないメソッドのパラメータとして、null 値を渡しています。 このパラメータは、@Nonnull として明示的にアノテートされていたか、または解析が常に null 値を利用すると示していました。 ### NP: null を返すかもしれないメソッドが @Nonnull 宣言されている (NP_NONNULL_RETURN_VIOLATION) このメソッドは、null 値を返すかもしれないのにメソッド (またはスーパークラスのメソッド) の戻り値に @Nonnull が宣言されています。 ### NP: null とわかっている値をその型のインスタンスなのか確かめている (NP_NULL_INSTANCEOF) チェックされている値が null であることが保証されているので、instanceof は常に faluse を返します。 これは安全で、誤解や論理エラーを指摘していないことを確認してください。 ### NP: null 値を利用している可能性がある (NP_NULL_ON_SOME_PATH) そこで分岐または文が実行されるなら null 値が利用されて NullPointerException が発生します。 もちろん、問題は分岐または文が実行不可能で、NullPointerException が決して発生する可能性がないということかもしれません。 それを決めるのは FindBugs の能力を超えています。 ### NP: null 値を例外経路で利用している可能性がある (NP_NULL_ON_SOME_PATH_EXCEPTION) 例外経路上のここで null 値が利用されています。コードが実行されると NullPointerException を引き起こすことがあります。 現在の FindBugs は実行不可能な例外経路を刈り取れていないので、誤検出かもしれないことに注意してください。 switch 文の default が多くの場合実行不可能なので FindBugs が例外経路である default を検討することに注意して下さい。 ### NP: メソッド呼び出しは非 null パラメータに対して null を渡している (NP_NULL_PARAM_DEREF) このメソッド呼び出しは非 null メソッドパラメータに対して null 値を渡しています。 パラメータは、常に非 null とすべきパラメータとしてアノテートされていたか、または解析が常に null 値を利用すると示していました。 ### NP: メソッド呼び出しは非 null パラメータに対して null を渡している (NP_NULL_PARAM_DEREF_ALL_TARGETS_DANGEROUS) すべての既知のターゲットメソッドが非 null であることをパラメータに要求する呼び出し場所で、おそらく null 値を渡しています。 パラメータは、常に非 null とすべきパラメータとしてアノテートされていたか、または解析が常に null 値を利用すると示していました。 ### NP: 非 null パラメータに null を渡している非仮想メソッドの呼び出し (NP_NULL_PARAM_DEREF_NONVIRTUAL) null の可能性がある値が 非 null メソッドパラメータに渡されています。 パラメータは、常に非 null とすべきパラメータとしてアノテートされていたか、または解析が常に null 値を利用すると示していました。 ### NP: Optional の戻り型を持つメソッドが明示的に null を返す (NP_OPTIONAL_RETURN_NULL) Optional の戻り型の使い方は、常に明示的に null を返すのは設計が望ましくないことを意味します。 null 値をこのようなケースで返すことは契約違反で、多分クライアントコードを破壊するでしょう。 ### NP: @Nonnull でアノテートされたフィールドに null を格納している (NP_STORE_INTO_NONNULL_FIELD) @Nonnull としてアノテートされたフィールドに null かもしれない値を格納しています。 ### NP: 書き込まれていないフィールドの読み出し (NP_UNWRITTEN_FIELD) プログラムは、決して null でない値を書き込むとは思われないフィールドの値を利用しています。 この値を利用すると NullPointerException が発生します。 ### Nm: クラスは equal(Object) を定義しています。equals(Object) にすべきですか? (NM_BAD_EQUAL) このクラスは、`equal(Object)` という名前のメソッドを定義しています。 このメソッドは、`java.lang.Object` の `equals(Object)` を (おそらく意図的に) オーバーライドしていません。 ### Nm: クラスは hashcode() を定義しています。hashCode() にすべきですか? (NM_LCASE_HASHCODE) このクラスは、`hashcode()` という名前のメソッドを定義しています。 このメソッドは、`java.lang.Object` の `hashCode` メソッドを (おそらく意図的に) オーバーライドしていません。 ### Nm: クラスは tostring() を定義しています。toString() にすべきですか? (NM_LCASE_TOSTRING) このクラスは、`tostring()` という名前のメソッドを定義しています。 このメソッドは、`java.lang.Object` の `toString` メソッドを (おそらく意図的に) オーバーライドしていません。 ### Nm: 明らかなメソッドとコンストラクタの混乱 (NM_METHOD_CONSTRUCTOR_CONFUSION) この正規のメソッドは定義しているクラスと同じ名前です。 これはコンストラクタを意図していた可能性が高いです。もしそうなら void 戻り値の宣言を除去してください。 偶然メソッドを定義したことが間違いだとわかり、適切なコンストラクタを定義したが、後方互換性のためにこのメソッドを除去できないならメソッドを非推奨にしてください。 ### Nm: 非常に紛らわしい名前のメソッド (NM_VERY_CONFUSING) 参照されたメソッドは、大文字の使い方だけによって異なる名前があります。 大文字の使い方が同一ならメソッドの1つが他のメソッドをオーバーライドするので、非常に紛らわしいです。 ### Nm: パラメータの間違ったパッケージのためにスーパークラスのメソッドをオーバーライドしていないメソッド (NM_WRONG_PACKAGE) パラメータの型がスーパークラスで対応するパラメータの型と正確に合致していないので、サブクラスのメソッドはスーパークラスの類似したメソッドをオーバーライドしていません。 たとえば以下のようなコードです。
>     import alpha.Foo;

>     public class A {
>         public int f(Foo x) { return 17; }
>     }
>     ----
>     import beta.Foo;

>     public class B extends A {
>         public int f(Foo x) { return 42; }
>     }
> クラス `B` で定義された `f(Foo)` メソッドは、クラス `A` の `f(Foo)` メソッドをオーバーライドしていません。 これは引数の型 `Foo` が違うパッケージだからです。 ### QBA: 論理式で boolean リテラル値を代入しているメソッド (QBA_QUESTIONABLE_BOOLEAN_ASSIGNMENT) このメソッドは、if または while の式の中の boolean 変数に boolean リテラル値 (true または false) を代入しています。 おそらく、これは = による代入ではなく、== を使用して論理比較をすることになっていました。 ### RANGE: 配列インデックスは範囲外 (RANGE_ARRAY_INDEX) 配列演算が行なわれますが、配列インデックスが範囲外なので実行時に ArrayIndexOutOfBoundsException が発生するでしょう。 ### RANGE: 配列の長さは範囲外 (RANGE_ARRAY_LENGTH) メソッドは、配列パラメータと長さパラメータで呼び出されますが、長さは範囲外です。 実行時に IndexOutOfBoundsException が発生するでしょう。 ### RANGE: 配列オフセットは範囲外 (RANGE_ARRAY_OFFSET) メソッドは、配列パラメータとオフセットパラメータで呼び出されますが、オフセットは範囲外です。 実行時に IndexOutOfBoundsException が発生するでしょう。 ### RANGE: 文字列インデックスは範囲外 (RANGE_STRING_INDEX) 文字列メソッドが呼び出されます。指定された文字列インデックスは範囲外です。 実行時に StringIndexOutOfBoundsException が発生するでしょう。 ### RC: 疑わしい参照比較 (RC_REF_COMPARISON) このメソッドは、 == または != 演算子を使用して2つの参照値を比較しています。 一般的にこの型のインスタンスを比較する正しい方法は `equals` メソッドです。 等価で識別可能なインスタンスを作成する可能性がありますが異なるオブジェクトなので == で比較しないでください。 参照によって一般に比較されるべきでないクラスの例は、`java.lang.Integer` 、`java.lang.Float` などです。 ### RCN: 既に利用していた値の null チェック (RCN_REDUNDANT_NULLCHECK_WOULD_HAVE_BEEN_A_NPE) ここで値が null なのかチェックしていますが、既に値を利用していたので null である可能性はありません。 値が null なら以前の利用で NullPointerException が発生していたでしょう。 基本的に、値が null であることを許すのかどうかに関係なく、このコードと以前の値の利用は一致しません。 チェックは冗長か、または以前の値の利用は誤りです。 ### RE: 正規表現のための無効な構文 (RE_BAD_SYNTAX_FOR_REGULAR_EXPRESSION) このコードは、正規表現の構文によると無効である正規表現を使用しています。 この文が実行されるとき PatternSyntaxException をスローします。 ### RE: 正規表現のために使われている File.separator (RE_CANT_USE_FILE_SEPARATOR_AS_REGULAR_EXPRESSION) このコードは、正規表現が必要な場所で、`File.separator` を使用しています。 これは `File.separator` がバックスラッシュである Windows プラットホームでは失敗します。 バックスラッシュは正規表現ではエスケープ文字として解釈されます。 その他の選択肢としては、`File.separator` の代わりに `File.separatorChar=='\\' ? "\\\\" : File.separator` を使用できます。 ### RE: 正規表現のために使われている "." または "|" (RE_POSSIBLE_UNINTENDED_PATTERN) String 機能が呼び出されていて、"." または "|" が引数として正規表現を取るパラメータに渡されています。 これは意図したことですか? たとえば `s.replaceAll(".", "/")` は、すべての文字が '/' 文字に置換された String を返す `s.split(".")` は、常に長さが0の String 配列を返す `"ab|cd".replaceAll("|", "/")` は、`"/a/b/|/c/d/"` を返す `"ab|cd".split("|")` は、6個の要素がある配列を返す: `[, a, b, |, c, d]` ### RV: 0から1の乱数値は整数値0に丸められる (RV_01_TO_INT) 0から1の乱数値は整数値0に丸められます。 おそらく整数に丸められる前に何か他のことによって乱数値を倍数にしたかったか、または `Random.nextInt(n)` メソッドを使いたかったのでしょう。 ### RV: 符号付き32ビットハッシュコードの絶対値を計算する間違った試み (RV_ABSOLUTE_VALUE_OF_HASHCODE) このコードは、ハッシュコードを生成して絶対値を計算しています。 ハッシュコードが `Integer.MIN_VALUE` なら結果は同様に負です (`Math.abs(Integer.MIN_VALUE) == Integer.MIN_VALUE` なので)。 文字列の2^32個に1個は `Integer.MIN_VALUE` のハッシュコードを持っていて、「polygenelubricants」、「GydZG_」、「DESIGNING WORKHOUSES」が該当します。 ### RV: 符号付き整数の乱数の絶対値を計算する間違った試み (RV_ABSOLUTE_VALUE_OF_RANDOM_INT) このコードは、符号付き整数の乱数を生成して絶対値を計算しています。 乱数ジェネレータで返される数が `Integer.MIN_VALUE` なら結果は同様に負です (`Math.abs(Integer.MIN_VALUE) == Integer.MIN_VALUE` なので)。 (同じ問題は long 値でも同様に起きます)。 ### RV: compareTo によって返された特定の値のコードチェック (RV_CHECK_COMPARETO_FOR_SPECIFIC_RETURN_VALUE) このコードは、compareTo または compare メソッドを呼び出して、戻り値が特定の値（たとえば1または-1） なのか確かめています。 これらのメソッドを呼び出すときは特定のゼロ以外の値ではなく、結果の符号だけをチェックするべきです。 多数または大部分の compareTo と比較メソッドは-1、0または1を返しますが、いくつかは他の値を返します。 ### RV: 作成した例外をスローするのではなく捨てている (RV_EXCEPTION_NOT_THROWN) このコードは、例外 (またはエラー) オブジェクトを作成していますが、何もしていません。 たとえば以下のようなコードです。
>     if (x < 0) {
>         new IllegalArgumentException("x must be nonnegative");
>     }
> おそらくプログラマの意図は、作成した例外をスローすることでした。
>     if (x < 0) {
>         throw new IllegalArgumentException("x must be nonnegative");
>     }
> ### RV: 戻り値を無視しているメソッド (RV_RETURN_VALUE_IGNORED) このメソッドの戻り値はチェックするべきです。 この警告の共通の原因は、オブジェクトが更新されると思って不変オブジェクトのメソッドを呼び出すことです。 たとえば以下のようなコードです。
>     String dateString = getHeaderField(name);
>     dateString.trim();
> プログラマは、`trim` メソッドが `dateString` によって参照される String オブジェクトが更新されると思っています。 しかし、String オブジェクトは不変で、`trim` メソッドが新しい String オブジェクトを返すのに無視しています。 このコードは、以下のように修正するべきです。
>     String dateString = getHeaderField(name);
>     dateString = dateString.trim();
> ### RpC: 条件テストの繰り返し (RpC_REPEATED_CONDITIONAL_TEST) このコードには条件テストが2回、つまり、1つめの条件テストが正しいとき、2つめの条件テストが実行されます (たとえば、`x == 0 || x == 0`)。 多分、2つめの条件テストは何か他のことを意図しています (たとえば、`x == 0 || y == 0`)。 ### SA: フィールドの自己代入 (SA_FIELD_SELF_ASSIGNMENT) このメソッドにはフィールドの自己代入があります。 たとえば以下のようなコードです。
>     int x;
>     public void foo() {
>         x = x;
>     }
> そのような代入は役に立たないので、論理エラーかタイプミスかもしれません。 ### SA: フィールドとそれ自身との自己比較 (SA_FIELD_SELF_COMPARISON) このメソッドは、フィールドをそれ自身と比較しています。 論理エラーかタイプミスかもしれません。正しいものを比較していることを確認してください。 ### SA: フィールドの無意味な自己演算 (たとえば、 x & x) (SA_FIELD_SELF_COMPUTATION) このメソッドは、フィールドと同じフィールドへの別の参照との無意味な計算を実行しています (たとえば、x & x または x - x)。 この計算の性質のため、演算は意味をなすとは思われないので、論理エラーかタイプミスかもしれません。 計算をチェックしてください。 ### SA: フィールドへの代入ではなくローカル変数への自己代入 (SA_LOCAL_SELF_ASSIGNMENT_INSTEAD_OF_FIELD) このメソッドにはローカル変数の自己代入があり、ローカル変数とフィールドが同じ名前です。 たとえば以下のようなコードです。
>         int foo;
>         public void setFoo(int foo) {
>             foo = foo;
>         }
> そのような代入は役に立ちません。そうではなく、フィールドに代入するつもりでしたか？ ### SA: ローカル変数とそれ自身との自己比較 (SA_LOCAL_SELF_COMPARISON) このメソッドは、ローカル変数をそれ自身と比較しています。論理エラーかタイプミスかもしれません。 正しいものを比較していることを確認してください。 ### SA: 変数の無意味な自己演算 (たとえば、x & x) (SA_LOCAL_SELF_COMPUTATION) このメソッドは、ローカル変数と同じ変数への別の参照との無意味な計算を実行しています (たとえば、x & x または x - x)。 この計算の性質のため、演算は意味をなすとは思われないので、論理エラーかタイプミスかもしれません。 計算をダブルチェックしてください。 ### SF: switch 文のフォールスルーのために格納が無効になっている (SF_DEAD_STORE_DUE_TO_SWITCH_FALLTHROUGH) 前の case で格納された値が switch 文のフォールスルーのためにここで上書きされています。 前の case の終わりに break または return を入れるのを忘れた可能性があります。 ### SF: スローする switch 文のフォールスルーのために格納が無効になっている (SF_DEAD_STORE_DUE_TO_SWITCH_FALLTHROUGH_TO_THROW) 前の case で格納された値が例外がスローされる場所で、switch 文のフォールスルーのためにここで失われています。 前の case の終わりに break または return を入れるのを忘れた可能性があります。 ### SIC: 非 static 内部クラスとスレッドローカルのデッドロック (SIC_THREADLOCAL_DEADLY_EMBRACE) このクラスは内部クラスですが、おそらく static 内部クラスにすべきです。 実際には内部クラスと外部クラスのスレッドローカルとの間にデッドロックの深刻な危険性があります。 内部クラスが static でないので、外部クラスへの参照を保持します。 スレッドローカルに内部クラスのインスタンスの参照があるなら、内部と外部のインスタンスの両方が到達可能になり、ガベージされません。 ### SIO: instanceof 演算子を使用した不必要な型チェック (SIO_SUPERFLUOUS_INSTANCEOF) オブジェクトが要求する型であるかどうかにかかわらず、静的に判定される instanceof 演算子を使用して型チェックをしています。 ### SQL: インデックスが0で PreparedStatement にアクセスしようとしているメソッド (SQL_BAD_PREPARED_STATEMENT_ACCESS) インデックスが0で、`PreparedStatement` の setXXX メソッドを呼び出しています。 インデックスは1から開始するので、これは常に間違いです。 ### SQL: インデックスが0で ResultSet にアクセスしようとしているメソッド (SQL_BAD_RESULTSET_ACCESS) インデックスが0で、`ResultSet` の getXXX、updateXXX メソッドを呼び出しています。 `ResultSet` のインデックスは1から開始するので、これは常に間違いです。 ### STI: interrupted メソッドを呼び出すために不要な currentThread メソッドを呼び出している (STI_INTERRUPTED_ON_CURRENTTHREAD) このメソッドは、`interrupted` メソッドを呼び出すために `Thread.currentThread()` を呼び出しています。 `interrupted` メソッドは static メソッドなので、`Thread.interrupted()` を使用するほうが単純明解です。 ### STI: スレッドインスタンスで static Thread.interrupted() を呼び出している (STI_INTERRUPTED_ON_UNKNOWNTHREAD) このメソッドは、カレントスレッドでない Thread オブジェクトであるように見える Thread オブジェクトで `Thread.interrupted()` を呼び出しています。 `interrupted` メソッドは static なので、作成者が意図したこととは異なるオブジェクトで呼び出されます。 ### Se: 直列化機構のために private にしなければならないメソッド (SE_METHOD_MUST_BE_PRIVATE) このクラスは、`Serializable` インタフェースを実装して、カスタム直列化/直列化復元のためのメソッドを定義しています。 しかし、そのメソッドが private として宣言されていないので、直列化/直列化復元 API によって無視されます。 ### Se: readResolve メソッドが static メソッドとして宣言されている (SE_READ_RESOLVE_IS_STATIC) `readResolve` メソッドが直列化機構で認識されるためには static メソッドとして宣言してはいけません。 ### TQ: 型修飾子でアノテーションされた値がその修飾子を付けてはならない値を必要とする場所で使われている (TQ_ALWAYS_VALUE_USED_WHERE_NEVER_REQUIRED) 型修飾子でアノテートされた値がその修飾子を付けてはならない値を必要とする場所で使われています。 より正確に、when=ALWAYS を指定した型修飾子でアノテートされた値が到達することが保証されているか同じ型修飾子で when=NEVER を指定する場所で使用しています。 たとえば、@NonNegative は型修飾子アノテーション @Negative(when=When.NEVER) の略称とします。 以下のコードは、return 文が ＠NonNegative 値を要求するが ＠Negative としてマークされている値を受け取るのでこの警告を生成します。
>     public @NonNegative Integer example(@Negative Integer value) {
>         return value;
>     }
> ### TQ: 互換性のない型修飾子による比較値 (TQ_COMPARING_VALUES_WITH_INCOMPATIBLE_TYPE_QUALIFIERS) 型修飾子アノテーションを指定した値がその修飾子のない値と比較しています。 より正確に、when=ALWAYS を指定した型修飾子でアノテートされた値が同じ型修飾子で when=NEVER を指定する値と比較しています。 たとえば、@NonNegative は型修飾子アノテーション @Negative(when=When.NEVER) の略称とします。 以下のコードは、return 文が @NonNegative 値を要求するが、@Negative としてマークされている値を受け取るのでこの警告を生成します。
>     public boolean example(@Negative Integer value1, @NonNegative Integer value2) {
>         return value1.equals(value2);
>     }
> ### TQ: 型修飾子を付けていないかもしれない値がその型修飾子を必要とする方法で常に使われている (TQ_MAYBE_SOURCE_VALUE_REACHES_ALWAYS_SINK) 型修飾子によって示された値のインスタンスではない可能性としてアノテートされた値です。 値は、その型修飾子によって示された値を必要とする方法で使われることが保証されています。 ### TQ: 型修飾子を付けているかもしれない値がその型修飾子を禁止する方法で常に使われている (TQ_MAYBE_SOURCE_VALUE_REACHES_NEVER_SINK) 型修飾子によって示された値のインスタンスである可能性としてアノテートされた値です。 値は、その型修飾子によって示された値を禁止する方法で使われることが保証されています。 ### TQ: 型修飾子でアノテートされていない値がその修飾子が付けられた値を必要とする場所で使われている (TQ_NEVER_VALUE_USED_WHERE_ALWAYS_REQUIRED) 型修飾子でアノテートされていない値がその修飾子が付けられた値を必要とする場所で使われています。 より正確に、when=NEVER を指定した型修飾子でアノテートされた値が同じ型修飾子で when=ALWAYS を指定する場所で使用しています。 ### TQ: 型修飾子がない値が修飾子を必要とする場所で使われている (TQ_UNKNOWN_VALUE_USED_WHERE_ALWAYS_STRICTLY_REQUIRED) 値が型修飾子アノテーションを必要とする方法で使われています。型修飾子は厳密なので、ツールは適切なアノテーションを指定していない値を拒絶します。 厳密なアノテーションを指定しているので値を型変換します。戻り値が厳密なアノテーションでアノテートされる同一性機能を定義してください。 これは厳密な型修飾子アノテーションで非アノテート値を値に変える唯一の方法です。 ### UMAC: 呼び出し不可能なメソッドが無名クラスで定義されている (UMAC_UNCALLABLE_METHOD_OF_ANONYMOUS_CLASS) この無名クラスは、直接呼び出されないスーパークラスのメソッドをオーバーライドしていないメソッドを定義しています。 他のクラスのメソッドが無名クラスで宣言されたメソッドを直接呼び出せないので、このメソッドは呼び出し不可能だと思われます。 メソッドは単にデッドコードであるかもしれません。しかし、メソッドがスーパークラスで宣言されるメソッドをオーバーライドすることを意図した可能性もあります。 そして、タイプミスまたは他の誤りのためにメソッドは、実際には意図しているメソッドをオーバーライドしません。 ### UR: コンストラクタで初期化されていないフィールドを読み出している (UR_UNINIT_READ) このコンストラクタは、まだ値が代入されていないフィールドを読み出しています。 多くの場合、プログラマがコンストラクタのパラメータの代わりに誤ってフィールドを使うときに起きます。 ### UR: スーパークラスのコンストラクタから呼び出されるメソッドで初期化されていないフィールドを読み出している (UR_UNINIT_READ_CALLED_FROM_SUPER_CONSTRUCTOR) このメソッドは、スーパークラスのコンストラクタで呼びされています。この時点では、クラスのフィールドはまだ初期化されていません。 これはたくさんの具象クラスを作るためです。以下のクラスを検討してください。
>     abstract class A {
>         int hashCode;
>         abstract Object getValue();

>         A() {
>             hashCode = getValue().hashCode();
>         }
>     }

>     class B extends A {
>         Object value;

>         B(Object v) {
>             this.value = v;
>         }

>         Object getValue() {
>             return value;
>         }
>     }
> `B` が構築されるとき、`B` のコンストラクタが `value` に値を設定する前に、`A` クラスのコンストラクタが呼び出されます。 したがって、`A` のコンストラクタが `getValue` を呼び出すとき、`value` の初期化されていない値が読み出されます。 ### USELESS_STRING: 名前のない配列で toString メソッドを呼び出している (DMI_INVOKING_TOSTRING_ON_ANONYMOUS_ARRAY) このコードは、無名の配列で `toString` メソッドを呼び出しています。「[C@16f0472」のようなかなり役に立たない結果を生成します。 配列のコンテンツを与え、読める文字列に変換するために `Arrays.toString()` を使用することを検討してください。 『Programming Puzzlers』の第3章、パズル12を参照してください。 ### USELESS_STRING: 配列で toString メソッドを呼び出している (DMI_INVOKING_TOSTRING_ON_ARRAY) このコードは、配列で `toString` メソッドを呼び出しています。「[C@16f0472」のようなかなり役に立たない結果を生成します。 配列のコンテンツを与え、読める文字列に変換するために `Arrays.toString()` を使用することを検討してください。 『Programming Puzzlers』の第3章、パズル12を参照してください。 ### USELESS_STRING: 書式文字列を使用して役に立たない方法で配列をフォーマットしている (VA_FORMAT_STRING_BAD_CONVERSION_FROM_ARRAY) 書式文字列でフォーマットされている引数の1つは配列です。 [I@304282 のように配列のコンテンツを表示しないかなり役に立たない書式を使用してフォーマットされます。 フォーマットで扱う前に `Arrays.asList(...)` を使用して配列をラップすることを検討してください。 ### UwF: null に設定されるだけのフィールド (UWF_NULL_FIELD) このフィールドに定数値 null を書き込みます。したがって、フィールドの読み出しは null を返します。 誤りをチェックしてください。役に立たないなら除去してください。 ### UwF: 書き込まれていないフィールド (UWF_UNWRITTEN_FIELD) このフィールドは決して書き込まれません。このフィールドからの読み出しはデフォルト値を返します。 誤りをチェックしてください (フィールドは初期化するべきでしたか？)。役に立たないなら除去してください。 ### VA: 可変長引数を期待しているメソッドにプリミティブ型の配列を渡している (VA_PRIMITIVE_ARRAY_PASSED_TO_OBJECT_VARARG) このコードは可変長引数をとるメソッドにプリミティブ型の配列を渡しています。 これはプリミティブ型の配列を保持するために長さが1の配列を作成してメソッドに渡します。 ### LG: ロガーの変更は OpenJDK の弱参照が原因で潜在的に失われる (LG_LOST_LOGGER_DUE_TO_WEAK_REFERENCE) OpenJDK は、潜在的非互換性を取り入れました。特に、`java.util.logging.Logger` は振る舞いが変更されています。 強参照を使用する代わりに弱参照を内部的に使用しています。 それは理にかなった変更ですが、残念ながらいくつかのコードは古い振る舞いに依存しています。 ロガーの構成を変更するとき、ロガーへの参照を捨てます。 つまり、ガベージコレクタはそのメモリを回収できます。それは、ロガーの構成が失われることを意味します。 たとえば、以下を検討してください。
>     public static void initLogging() throws Exception {
>         Logger logger = Logger.getLogger("edu.umd.cs");
>         logger.addHandler(new FileHandler()); // ロガーの構成の変更
>         logger.setUseParentHandlers(false); // 別のロガーの構成の変更
>     }
> ロガーの参照は、メソッドの終わり (メソッドは脱出しません) で失われるので、 `initLogging` の呼び出しの後でガベージコレクションの循環があるなら、ロガー構成は失われます (なぜなら Logger は弱参照を保持するだけなので)。
>     public static void main(String[] args) throws Exception {
>         initLogging(); // ファイルハンドラーをロガーに追加する
>         System.gc(); // ロガーの構成が失われる
>         Logger.getLogger("edu.umd.cs").info("Some message"); // 期待したようにファイルに記録されません
>     }
> Ulf Ochsenfahrt と Eric Fellheimer ### OBL: ストリームやリソースのクリーンアップに失敗するかもしれないメソッド (OBL_UNSATISFIED_OBLIGATION) このメソッドは、ストリーム、データベースオブジェクト、またはクリーンアップ操作を明示的に必要としている他のリソースのクリーンアップ (クローズする、片付ける) に失敗するかもしれません。 一般的にメソッドがストリープや他のリソースを開いたなら、メソッドはストリームやリソースがメソッドが戻る前にクリーンアップされることを確認するために try/finally ブロックを使用するべきです。 このバグパターンは、OS_OPEN_STREAM と ODR_OPEN_DATABASE_RESOURCE と基本的に同じですが異なる (そして、うまくいけばより良い) 静的解析技術に基づいています。 私たちは、このバグパターンの有効性についてのフィードバックを得ることに関心があります。 どちらかの方法でフィードバックを送ってください。 send email to findbugs@cs.umd.edu file a bug report: http://findbugs.sourceforge.net/reportingBugs.html 特に、このバグパターンの誤検出抑制探索法は詳細にわたって調整されていないので、誤検出についてのレポートは我々の助けになります。 解析技術の説明は、Weimer と Necula による Finding and Preventing Run-Time Error Handling Mistakes を参照してください。 ### OBL: チェック例外でストリームやリソースのクリーンアップに失敗するかもしれないメソッド (OBL_UNSATISFIED_OBLIGATION_EXCEPTION_EDGE) このメソッドは、ストリーム、データベースオブジェクト、またはクリーンアップ操作を明示的必要としている他のリソースのクリーンアップ (クローズする、片付ける) に失敗するかもしれません。 一般的にメソッドがストリープや他のリソースを開いたなら、メソッドはストリームやリソースがメソッドが戻る前にクリーンアップされることを確認するために try/finally ブロックを使用するべきです。 このバグパターンは、OS_OPEN_STREAM と ODR_OPEN_DATABASE_RESOURCE と基本的に同じですが異なる (そして、うまくいけばより良い) 静的解析技術に基づいています。 私たちは、このバグパターンの有効性についてのフィードバックを得ることに関心があります。 どちらかの方法でフィードバックを送ってください。 send email to findbugs@cs.umd.edu file a bug report: http://findbugs.sourceforge.net/reportingBugs.html 特に、このバグパターンの誤検出抑制探索法は詳細にわたって調整されていないので、誤検出についてのレポートは我々の助けになります。 解析技術の説明は、Weimer と Necula による Finding and Preventing Run-Time Error Handling Mistakes を参照してください。 ### Dm: 呼び出したメソッドの Locale パラメータの使用を検討する (DM_CONVERT_CASE) 文字列がプラットホームのデフォルトエンコーディングを使用して大文字、小文字に変換されています。 国際文字で使われると不適切な変換になることがあります。 String.toUpperCase(Locale l) String.toLowerCase(Locale l) ### Dm: デフォルトエンコーディングへの依存 (DM_DEFAULT_ENCODING) byte から String (または String から byte) への変換で、デフォルトプラットホームエンコーディングが適切だと仮定するメソッドの呼び出しを発見しました。 これはアプリケーションの振る舞いがプラットホーム間で異なる原因となります。代替 API を使用して、文字セット名または Charset オブジェクトを明示的に指定して下さい。 ### DP: doPrivileged ブロック内で作成されるべきクラスローダ (DP_CREATE_CLASSLOADER_INSIDE_DO_PRIVILEGED) このコードはクラスローダを作成していますが、セキュリティ管理がインストールされるなら許可が必要です。 このコードがセキュリティ許可がないコードによって呼び出されるなら、クラスローダの作成は doPrivileged ブロックの中で行う必要があります。 ### DP: doPrivileged ブロック内で呼び出すべきメソッド (DP_DO_INSIDE_DO_PRIVILEGED) このコードは、セキュリティ許可チェックが必要なメソッドを呼び出しています。 このコードにセキュリティ許可が与えられるとしても、セキュリティ許可を持たないコードによって呼び出されるなら doPrivileged ブロックの中で呼び出す必要があります。 ### EI: 可変オブジェクトへの参照を返すことによって内部表現を暴露するかもしれないメソッド (EI_EXPOSE_REP) オブジェクトのフィールドに格納された可変オブジェクトの参照を返すと、オブジェクトの内部表現を暴露します。 インスタンスが信頼できないコードによってアクセスされるなら、可変オブジェクトのチェックされていない変更がセキュリティや他の重要なプロパティを危うくするでしょう。 何か違うことをする必要があります。オブジェクトの新しいコピーを返すことは、多くの状況でより良いアプローチです。 ### EI2: 可変オブジェクトへの参照を取り込むことによって内部表現を暴露するかもしれないメソッド (EI_EXPOSE_REP2) このコードは、オブジェクトの内部表現に外部の可変オブジェクトの参照を格納しています。 インスタンスが信頼できないコードによってアクセスされるなら、可変オブジェクトのチェックされていない変更がセキュリティや他の重要なプロパティを危うくするでしょう。 何か違うことをする必要があります。オブジェクトの新しいコピーを返すことは、多くの状況でより良いアプローチです。 ### FI: ファイナライザは public ではなく protected にすべき (FI_PUBLIC_SHOULD_BE_PROTECTED) このクラスの `finalize` メソッドは public ではなく、protected にすべきです。 ### MS: static フィールドに可変オブジェクトを格納することによって、内部の静的状態を暴露するかもしれないメソッド (EI_EXPOSE_STATIC_REP2) このコードは、static フィールドに外部の可変オブジェクトを格納しています。 可変オブジェクトのチェックされていない変更がセキュリティや他の重要なプロパティを危うくするでしょう。 何か違うことをする必要があります。オブジェクトのコピーを保存することは、多くの状況でより良いアプローチです。 ### MS: final でないフィールドは悪意のあるコードから保護できない (MS_CANNOT_BE_FINAL) この可変 static フィールドは悪意のあるコードや偶然別のパッケージによって変更できます。 残念ながらこのような使い方は簡単に解決できません。 ### MS: 配列を返すことによって内部表現を暴露するかもしれない public static メソッド (MS_EXPOSE_REP) public static メソッドは、クラスの 静的な状態の一部である配列の参照を返します。 このメソッドを呼び出すどんなコードも、基底配列を自由に変更できます。 解決策は、配列のコピーを返すことです。 ### MS: final かつパッケージプロテクテッドにすべきフィールド (MS_FINAL_PKGPROTECT) この可変 static フィールドは悪意のあるコードや偶然別のパッケージによって変更できます。 フィールドは、脆弱性を回避するために final および/またはパッケージプロテクテッドにします。 ### MS: 可変配列のフィールド (MS_MUTABLE_ARRAY) この final static フィールドは配列を参照しているので、悪意のあるコードや偶然別のパッケージによってアクセスできます。 このコードは、配列のコンテンツを自由に変更できます。 ### MS: 可変コレクションのフィールド (MS_MUTABLE_COLLECTION) 可変コレクションのインスタンスが final static フィールドに割り当てられています。 したがって、 悪意のあるコードや偶然別のパッケージによって変更できます。 脆弱性を避けるために Collections.unmodifiableSet/List/Map などでこのフィールドをラップすることを検討してください。 ### MS: パッケージプロテクテッドにすべき可変コレクションのフィールド (MS_MUTABLE_COLLECTION_PKGPROTECT) 可変コレクションのインスタンスが final static フィールドに割り当てられています。 したがって、悪意のあるコードや偶然別のパッケージによって変更できます。 フィールドは脆弱性を避けるためにパッケージプロテクテッドにできます。 代わりに Collections.unmodifiableSet/List/Map などでこのフィールドをラップしても脆弱性を避けることができます。 ### MS: 可変 Hashtable のフィールド (MS_MUTABLE_HASHTABLE) この final static フィールドは Hashtable を参照しているので、悪意のあるコードや偶然別のパッケージによってアクセスできます。 このコードは、Hashtable のコンテンツを自由に変更できます。 ### MS: インタフェースから移動してパッケージプロテクテッドにすべきフィールド (MS_OOI_PKGPROTECT) インタフェースに定義された final static フィールドが配列や Hashtable などの可変オブジェクトを参照しています。 この可変オブジェクトは悪意のあるコードや偶然別のパッケージによって変更できます。 これを解決するためにフィールドはクラスへ移動する必要があり、脆弱性を回避するためにパッケージプロテクテッドにします。 ### MS: パッケージプロテクテッドにすべきフィールド (MS_PKGPROTECT) この可変 static フィールドは悪意のあるコードや偶然別のパッケージによって変更できます。 フィールドは、脆弱性を回避するためにパッケージプロテクテッドにします。 ### MS: final にすべきフィールド (MS_SHOULD_BE_FINAL) final でない public static フィールドは悪意のあるコードや偶然別のパッケージによって変更できます。 フィールドは、脆弱性を回避するために final にします。 ### MS: final でないフィールドはリファクタリングするべき (MS_SHOULD_BE_REFACTORED_TO_BE_FINAL) final でない public static フィールドは悪意のあるコードや偶然別のパッケージによって変更できます。 フィールドは、脆弱性を回避するために final にします。 しかしながら、スタティックイニシャライザには複数のフィールドへの書き込みがあるので、何らかのリファクタリングを必要とするでしょう。 ### AT: 並行抽象の呼び出しシーケンスはアトミックではないかもしれない (AT_OPERATION_SEQUENCE_ON_CONCURRENT_ABSTRACTION) このコードには並行抽象化 （たとえば、並行ハッシュマップ） の呼び出しシーケンスがあります。 これらの呼び出しは原子的に実行されません。 ### DC: フィールドのダブルチェックの可能性 (DC_DOUBLECHECK) このメソッドにはダブルチェックロッキングのインスタンスがあるかもしれません。このイディオムは、Java のメモリモデルでは正しくありません。 詳細は、http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html を参照してください。 ### DC: 部分的に初期化されたオブジェクトを暴露する可能性がある (DC_PARTIALLY_CONSTRUCTED) ダブルチェックロッキングと共に遅延初期化フィールドを使用するメソッドのようです。 フィールドが正しく volatile として宣言される間にオブジェクトの内部構造がフィールドに割り当てられた後で変更される可能性があります。 したがって、他のスレッドが部分的に初期化されたオブジェクトを見るかもしれません。 この問題を直すために、最初にローカル変数をオブジェクトに格納して、完全に構築した後で volatile フィールドを保存することを考えてください。 ### DL: Boolean の同期化 (DL_SYNCHRONIZATION_ON_BOOLEAN) `Boolean` のようなボクシングされたプリミティブ型の定数で同期化しています。
>     private static Boolean inited = Boolean.FALSE;

>     synchronized(inited) {
>         if (!inited) {
>             init();
>             inited = Boolean.TRUE;
>         }
>     }
> 一般には2つの `Boolean` オブジェクトだけが存在しています。 このコードは他の無関係なコードと同じオブジェクトで同期化している可能性があるので、無応答やデッドロックの原因になります。 ### DL: デッドロックの原因になる可能性があるボクシングされたプリミティブ型の同期化 (DL_SYNCHRONIZATION_ON_BOXED_PRIMITIVE) このコードは、Integer のようなボクシングされたプリミティブ型の定数で同期化しています。
>     private static Integer count = 0;

>     synchronized(count) {
>         count++;
>     }
> `Integer` オブジェクトはキャッシュして共有できます。 他の無関係なコードと同じオブジェクトで同期化している可能性があるので、無応答やデッドロックの原因になります。 CERT の CON08-J. Do not synchronize on objects that may be reused を参照してください。 ### DL: 正準化した文字列の同期化 (DL_SYNCHRONIZATION_ON_SHARED_CONSTANT) このコードは、正準化した文字列で同期化しています。
>     private static String LOCK = "LOCK";

>     synchronized(LOCK) {
>         ...
>     }
> 文字列定数は正準化され、Java 仮想マシンによってロードされたすべてのクラス全体で共有されます。 したがって、これは他のコードがロックしているかもしれない何かをロックしている可能性があります。 これはブロッキングとデッドロックの振る舞いの診断を難しくして、とても奇妙な結果になる可能性があります。 詳細は、http://www.javalobby.org/java/forums/t96352.html と http://jira.codehaus.org/browse/JETTY-352 を参照してください。 ### DL: ボクシングされたプリミティブ値の同期化 (DL_SYNCHRONIZATION_ON_UNSHARED_BOXED_PRIMITIVE) このコードは、明らかに共有されていない `Integer` のようなボクシングされたプリミティブ型で同期化しています。
>     private static final Integer fileLock = new Integer(1);

>     synchronized(fileLock) {
>         .. do something ..
>     }
> このコードは、 fileLock を以下のように宣言するとより良くなります。
>     private static final Object fileLock = new Object();
> 既存のコードとしては間違っていないかもしれないが、紛らわしいので将来リファクタリングするべきかもしれません。 たとえば、IntelliJ の "Remove Boxing" のようなリファクタリングは Java 仮想マシンを通して共有される正準化された `Integer` オブジェクトを使用するように置き換えてしまい、非常に紛らわしい振る舞いと潜在的デッドロックの原因になります。 ### Dm: Condition で wait メソッドを呼び出している (DM_MONITOR_WAIT_ON_CONDITION) このメソッドは、`java.util.concurrent.locks.Condition` オブジェクトで `wait` メソッドを呼び出しています。 `Condition` オブジェクトを待機させるためには `Condition` インタフェースで定義された `await` メソッドを使用するべきです。 ### Dm: デフォルトの空の run メソッドを使用して作成されたスレッド (DM_USELESS_THREAD) このメソッドは、`Thread` クラスから派生した `run` メソッドを指定していないか、`Runnable` オブジェクトを渡すことなく、スレッドを作成しています。 このスレッドは、時間の無駄です。 ### ESync: 空の synchronized ブロック (ESync_EMPTY_SYNC) このコードには空の synchronized ブロックがあります。
>     synchronized() {
>     }
> 空の synchronized ブロックは巧妙で正しく使用するのは困難です。 空の synchronized ブロックはわざとらしくて決して良い解決策ではありません。 ### IS: 一貫性のない同期化 (IS2_INCONSISTENT_SYNC) このクラスのフィールドは、同期化に関して一貫性なくアクセスされるように見えます。 このバグレポートは、バグパターンディテクタが以下のように判断したことを示します。 クラスは、ロックされたアクセスとアンロックされたアクセスが混在していて クラスは、javax.annotation.concurrent.NotThreadSafe としてアノテートされません 少なくとも1つのロックされたアクセスがクラス自身のメソッドの1つによって実行され、 読み出しの2倍の重み付けをした書き込みで、非同期フィールドのアクセス (読み出しと書き込み) 数がすべてのアクセスのわずか1/3 ディテクタがどこでフィールドが同期化なしでアクセスされると信じていたかを示すコードの場所に「非同期アクセス」というラベルがついているノードを選択できます。 不正確ないろいろな原因がこのディテクタにあることに注意してください。 たとえば、ディテクタはロックを保持されるすべての状況を静的に検出できるわけではありません。 また、ディテクタがロックされたアクセスとアンロックされたアクセスの区別が正確なときでも、問題のコードは依然として正しいかもしれません。 ### IS: 並行アクセスに対してガードされていないフィールド (IS_FIELD_NOT_GUARDED) このフィールドは、net.jcip.annotations.GuardedBy または javax.annotation.concurrent.GuardedBy でアノテートされていますが、アノテーションに違反すると思われる方法でアクセスできます。 ### JLM: Lock で同期化している (JLM_JSR166_LOCK_MONITORENTER) このメソッドは、`java.util.concurrent.locks.Lock` を実装したオブジェクトで同期化しています。 そのようなオブジェクトは `synchronized (...)` 構文よりも `acquire()`/`release()` を使用してロックとロックの解除をします。 ### JLM: java.util.concurrent のインスタンスで同期化している (JLM_JSR166_UTILCONCURRENT_MONITORENTER) このメソッドは、java.util.concurrent パッケージのクラス (またはサブクラス) のインスタンスで同期化しています。 これらのクラスのインスタンスは、`synchronized` の使用とは違う互換性のないそれら自身の並行制御メカニズムを持っています。 たとえば、`AtomicBoolean` で同期しても、他のスレッドが `AtomicBoolean` を変更するのを防ぎません。 そのようなコードは正しいかもしれないが、将来コードを維持しなければならない人々を混乱させるかもしれないので慎重にレビューし文書化するべきです、 ### JLM: util.concurrent 抽象でモニタスタイルの wait メソッドを使用している (JML_JSR166_CALLING_WAIT_RATHER_THAN_AWAIT) このメソッドは、`await()` メソッド、`signal` メソッド、`signalAll` メソッドを提供するオブジェクト (たとえば、util.concurrent の Condition オブジェクト) で、`wait` メソッド、`notify` メソッド、`notifyAll` メソッドを呼び出しています。 これはおそらくあなたが望むことではありません。たとえそれを望むとしても、他の開発者が非常に紛らわしいことを理解して、設計を変更することを検討するべきです。 ### LI: static フィールドの間違った遅延初期化 (LI_LAZY_INIT_STATIC) このメソッドにはvolatile でない static フィールドの非同期な遅延初期化があります。 コンパイラやプロセッサが命令を並べ替えるかもしれないので、メソッドが複数のスレッドによって呼び出されるなら、 スレッドは完全に初期化されたオブジェクトを見るとは保証されていません。 フィールドにアクセスした際に、中途半端に初期化されたインスタンスが見えてしまう危険があります。 この問題を修正するためにフィールドを volatile にできます。 詳細は、Java Memory Model web site を参照してください。 ### LI: 更新される static フィールドの間違った遅延初期化 (LI_LAZY_INIT_UPDATE_STATIC) このメソッドにはstatic フィールドの非同期な遅延初期化があります。 フィールドが設定された後で、その場所に格納されるオブジェクトはさらに更新されるかアクセスされます。 それが設定されるとすぐに、フィールドを設定することは他のスレッドに見えます。 フィールドを設定するさらなるアクセスがオブジェクトを初期化するのに役に立つなら、 それが完全に初期化されるまでどんな他のスレッドも格納されたオブジェクトにアクセスするのを防がないかぎり、非常に深刻なマルチスレッドバグがあります。 たとえメソッドが複数のスレッドによって決して呼び出されないと確信していても、 それは、フィールドに設定している値が完全にデータを読み込まれるか初期化されるまで、 static フィールドを設定しないほうが良いかもしれません。 ### ML: フィールドを同期化でガードしようとする無駄な試み (ML_SYNC_ON_FIELD_TO_GUARD_CHANGING_THAT_FIELD) このメソッドは、フィールドの同時更新に対して同期化でガードしようとしています。しかし、フィールドをガードするとフィールドではなく、フィールドが参照するオブジェクトのロックを獲得します。 これはあなたが必要とする相互排除ができないかもしれません。 他のスレッドは (他の目的のための) 参照されたオブジェクトのロックを獲得するかもしれません。 このパターンの例は以下のようになります。
>     private Long myNtfSeqNbrCounter = new Long(0);
>     private Long getNotificationSequenceNumber() {
>          Long result = null;
>          synchronized(myNtfSeqNbrCounter) {
>              result = new Long(myNtfSeqNbrCounter.longValue() + 1);
>              myNtfSeqNbrCounter = new Long(result.longValue());
>          }
>          return result;
>     }
> ### ML: 更新されるフィールドで同期化しているメソッド (ML_SYNC_ON_UPDATED_FIELD) このメソッドは、可変フィールドから参照されたオブジェクトで同期化しています。 異なるスレッドが異なるオブジェクトで同期化しているかもしれないので、有用な意味を持っている可能性が低いです。 ### MSF: 可変サーブレットフィールド (MSF_MUTABLE_SERVLET_FIELD) Web サーバは、一般的にサーブレットや JSP クラスのインスタンスを1つだけ作成します (すなわち、シングルトンとして扱います)。 複数のスレッドが複数同時のリクエストに応えるためにそのインスタンスでメソッドを呼び出します。 したがって、一般に可変インスタンスフィールドは競合状態を作ります。 ### MWN: 不整合な notify メソッド (MWN_MISMATCHED_NOTIFY) このメソッドは、オブジェクトで明らかにロックを保持することなく `Object.notify()` や `Object.notifyAll()` を呼び出しています。 保持されるロックがない状態で、`notify` メソッドや `notifyAll` メソッドを呼び出すことは、`IllegalMonitorStateException` をスローすることになります。 ### MWN: 不整合な wait メソッド (MWN_MISMATCHED_WAIT) このメソッドは、オブジェクトで明らかにロックを保持することなく、`Object.wait()` を呼び出しています。 保持されるロックがない状態で、`wait` メソッドを呼び出すことは、`IllegalMonitorStateException` をスローすることになります。 ### NN: 裸の notify メソッド (NN_NAKED_NOTIFY) `notify` メソッドまたは `notifyAll` メソッドへの呼び出しは可変オブジェクト状態にどんな (明らかな) 付随的な変更ももたらされませんでした。 一般的に別のスレッドが期待しているいくつかの条件が真になったので、モニタで `notify` メソッドが呼び出されます。 しかしながら、意味がある条件のために両方のスレッドに見えるヒープオブジェクトを含まなければなりません。 可変オブジェクトの状態変更が通知があるメソッドを呼び出したメソッドで起こったかもしれないので、このバグが必ずしもエラーを示すというわけではありません。 ### NP: 同じフィールドでの同期化と null チェック (NP_SYNC_AND_NULL_CHECK_FIELD) フィールドは同期化しているので、おそらく null ではないと思われます。 null のフィールドを同期化すると NullPointerException がスローされるので、null チェックは無意味になります。 別のフィールドで同期化したほうがよいです。 ### No: notifyAll メソッドではなく notify メソッドを使用している (NO_NOTIFY_NOT_NOTIFYALL) このメソッドは、`notifyAll` メソッドではなく `notify` メソッドを呼び出しています。 モニタが複数の条件のために多くの場合使われます。 `notify` メソッドの呼び出しは1つのスレッドを起こすだけで起こされたスレッドは呼び出し元が満たした待機条件の1つではないかもしれないことを意味しています。 ### RS: readObject メソッドを同期化しているクラス (RS_READOBJECT_SYNC) この直列化可能クラスは同期化する `readObject` メソッド を定義していますが、 直列化復元によって作成されるオブジェクトは1つのスレッドによってだけ到達可能です。 したがって、`readObject` メソッドは同期化する必要がありません。 `readObject` メソッドそのものが別のスレッドに見えるようになるオブジェクトの原因になっているなら非常に疑わしいコーディングスタイルの例です。 ### RV: putIfAbsent の戻り値は無視されて putIfAbsent に渡した値は再利用された (RV_RETURN_VALUE_OF_PUTIFABSENT_IGNORED) `putIfAbsent` メソッドは、1つの値が与えられたキー (非存在が成功するかどうかの第一の値) と関連することを確認するために使われます。 戻り値を無視して中で渡される値への参照を保持するなら、マップのキーと関連する1つではない値を保持する危険性を冒します。 どれを使用するかが重要であり、マップに格納できないものを使うとプログラムは誤った振る舞いをします。 ### Ru: スレッドで run メソッドを呼び出している (RU_INVOKE_RUN) このメソッドは、スレッドで 明示的に `run` メソッドを呼び出しています。 一般的にクラスは新しいスレッドで自己の `run` メソッドを呼び出してもらうために `Runnable` インタフェースを実装します。 その場合は、`Thread.start()` を呼び出すのが正しいです。 ### SC: Thread.start() を呼び出しているコンストラクタ (SC_START_IN_CTOR) コンストラクタがスレッドを開始しています。クラスが拡張され、サブクラスが作られるなら間違っていそうです。 なぜなら、サブクラスのコンストラクタでスレッドが開始される前にスーパークラスのスレッドが開始されてしまうためです。 ### SP: スピンロックをしているメソッド (SP_SPIN_ON_FIELD) このメソッドは、フィールドを読み出すループで回り続けます。 コンパイラがフィールドの読み出しをループの外に出すかもしれません。コードを無限ループに変えます。 正しい同期化 (wait/notify を呼び出すように含む) を使うようにクラスを変更するべきです。 ### STCAL: static Calendar の呼び出し (STCAL_INVOKE_ON_STATIC_CALENDAR_INSTANCE) たとえ JavaDoc にそれに関する手がかりがないとしても、Calendar はマルチスレッドでの使用は本質的に安全ではありません。 ディテクタは、static フィールドから得られた Calendar のインスタンスの呼び出しを発見しました。 これは疑わしく見えます。 詳細については、Sun Bug #6231579 や Sun Bug #6178997 を参照してください。 ### STCAL: static DateFormat の呼び出し (STCAL_INVOKE_ON_STATIC_DATE_FORMAT_INSTANCE) JavaDoc に書かれているように DateFormat はマルチスレッドでの使用は本質的に安全ではありません。 ディテクタは、static フィールドから得られた DateFormat のインスタンスの呼び出しを発見しました。 これは疑わしく見えます。 詳細については、Sun Bug #6231579 や Sun Bug #6178997 を参照してください。 ### STCAL: static Calendar フィールド (STCAL_STATIC_CALENDAR_INSTANCE) たとえ JavaDoc にそれに関する手がかりがないとしても、Calendar はマルチスレッドでの使用は本質的に安全でありません。 正しい同期化をしないでスレッド境界の向こうで1つのインスタンスを共有することは、アプリケーションの誤動作になります。 JDK 5.0に比べて JDK 1.4 のほうが問題が表面化するように思われ、おそらく sun.util.calendar.BaseCalendar.getCalendarDateFromFixedDate() の ArrayIndexOutOfBoundsExceptions や IndexOutOfBoundsExceptions がランダムに発生します。 直列化問題も経験するかもしれません。インスタンスフィールドを使用することを推奨します。 詳細については、Sun Bug #6231579 や Sun Bug #6178997 を参照してください。 ### STCAL: static DateFormat (STCAL_STATIC_SIMPLE_DATE_FORMAT_INSTANCE) JavaDoc に書かれているように DateFormat はマルチスレッドでの使用は本質的に安全ではありません。 正しい同期化をしないでスレッド境界の向こうで1つのインスタンスを共有することは、アプリケーションの誤動作になります。 JDK 5.0に比べて JDK 1.4 のほうが問題が表面化するように思われ、おそらく sun.util.calendar.BaseCalendar.getCalendarDateFromFixedDate() の ArrayIndexOutOfBoundsExceptions や IndexOutOfBoundsExceptions がランダムに発生します。 直列化問題も経験するかもしれません。インスタンスフィールドを使用することを推奨します。 詳細については、Sun Bug #6231579 や Sun Bug #6178997 を参照してください。 ### SWL: ロックを保持して Thread.sleep() を呼び出しているメソッド (SWL_SLEEP_WITH_LOCK_HELD) このメソッドは、ロックを保持して、`Thread.sleep()` を呼び出しています。 他のスレッドがロックを獲得するために待機しているかもしれないので、ひどい性能とスケーラビリティ、またはデッドロックの原因になるかもしれません。 ロックで `wait` メソッドを呼び出すことはかなり良い考えで、ロックを解除して他のスレッドが実行するのを許可します。 ### TLW: 2つ以上のロックを保持して wait メソッドを呼び出している (TLW_TWO_LOCK_WAIT) 2つ以上のロックを保持して、モニタで待機させるとデッドロックを引き起こすことがあります。 `wait` メソッドを呼び出すと、待機しているオブジェクトのロックを解除するだけで、その他のロックは解除しません。 これは必ずしもバグではありませんが厳密に調べる価値があります。 ### UG: 同期化していない get メソッド、同期化している set メソッド (UG_SYNC_SET_UNSYNC_GET) このクラスには類似した名前の get メソッドと set メソッドがあり、set メソッドは同期化していて、get メソッドは同期化していません。 get メソッドの呼び出し元がオブジェクトの一貫した状態を必ずしも見るというわけではないので、実行時に間違った振る舞いの原因になることがあります。 get メソッドは同期化するべきです。 ### UL: すべての経路でロックが解除されないメソッド (UL_UNRELEASED_LOCK) このメソッドは、JSR-166(`java.util.concurrent`) のロックを獲得していますが、メソッドからのすべての経路で解除していません。 一般的に JSR-166のロックを使用するための正しいイディオムは以下のようになります。
>     Lock l = ...;
>     l.lock();
>     try {
>         // do something
>     } finally {
>         l.unlock();
>     }
> ### UL: すべての例外経路でロックが解除されないメソッド (UL_UNRELEASED_LOCK_EXCEPTION_PATH) このメソッドは、JSR-166(`java.util.concurrent`) のロックを獲得していますが、メソッドからのすべての例外経路で解除していません。 一般的に JSR-166のロックを使用するための正しいイディオムは以下のようになります。
>     Lock l = ...;
>     l.lock();
>     try {
>         // do something
>     } finally {
>         l.unlock();
>     }
> ### UW: wait メソッドの無条件呼び出し (UW_UNCOND_WAIT) このメソッドには条件制御フローによってガードされない `java.lang.Object.wait()` の呼び出しがあります。 このコードは、`wait` メソッドを呼び出す前に待機するつもりだった条件が既に満たされていないことを確かめるべきです。 どんな前の通知も無視されます。 ### VO: volatile フィールドへのインクリメントはアトミックではない (VO_VOLATILE_INCREMENT) このコードは、volatile フィールドをインクリメントしています。 volatile フィールドのインクリメントはアトミックではありません。 複数のスレッドが同時にフィールドをインクリメントすると、インクリメントが失われる可能性があります。 ### VO: 配列への volatile 参照は、配列要素を volatile として扱わない (VO_VOLATILE_REFERENCE_TO_ARRAY) 配列に volatile 参照を宣言していますが、あなたが望むものではないかもしれません。 配列への volatile 参照は、配列への参照の読み出し、書き込みは volatile として扱われますが、配列要素は volatile として扱われません。 配列要素を volatile として扱いたいのであれば、J2SE 5.0で提供された java.util.concurrent パッケージのアトミック配列クラスを使用する必要があります。 ### WL: クラスリテラルではなく getClass で同期化している (WL_USING_GETCLASS_RATHER_THAN_CLASS_LITERAL) このインスタンスメソッドは、`this.getClass()` で同期化しています。 このクラスがサブクラス化されるなら、サブクラスはおそらく意図したことではないサブクラスのためにクラスオブジェクトで同期化します。 たとえば、`java.awt.Label` の以下のコードを検討してください。
>     private static final String base = "label";
>     private static int nameCounter = 0;

>     String constructComponentName() {
>         synchronized (getClass()) {
>             return base + nameCounter++;
>         }
>     }
> `Label` のサブクラスは同じサブクラスで同期化しません。データレースを生じさせます。 代わりに、このコードは、`Label.class` で同期化するべきです。
>     private static final String base = "label";
>     private static int nameCounter = 0;

>     String constructComponentName() {
>         synchronized (Label.class) {
>             return base + nameCounter++;
>         }
>     }
Jason Mehrens によって寄贈されたバグパターン ### WS: writeObject メソッドは同期化しているがその他のメソッドは同期化していないクラス (WS_WRITEOBJECT_SYNC) このクラスには同期化している `writeObject` メソッドがあります。 しかしながら、クラスのその他のメソッドは同期化していません。 ### Wa: Condition.await() がループの中にない (WA_AWAIT_NOT_IN_LOOP) このメソッドは、ループの中にない `java.util.concurrent.await()` (またはそのバリエーション) を呼び出しています。 オブジェクトが複数の条件のために使われるなら、呼び出し元が待機するつもりだった条件は実際には発生しないかもしれません。 ### Wa: wait メソッドがループの中にない (WA_NOT_IN_LOOP) このメソッドは、ループの中にない `java.lang.Object.wait()` を呼び出しています。 モニタが複数の条件のために使われるなら、呼び出し元が待機するつもりだった条件は実際には発生しないかもしれません。 ### Bx: プリミティブ値がボクシングされて、すぐにアンボクシングされる (BX_BOXING_IMMEDIATELY_UNBOXED) プリミティブ値がボクシングされて、すぐにアンボクシングされます。 おそらくアンボクシングされた値が必要な場所で手動でボクシングをしているためです。 その結果、コンパイラにボクシングの機能を取り消すことを強制しています。 ### Bx: プリミティブ値がプリミティブ型の型変換をするためにボクシングされて、アンボクシングされる (BX_BOXING_IMMEDIATELY_UNBOXED_TO_PERFORM_COERCION) プリミティブ値がコンストラクタでボクシングされて、すぐに異なるプリミティブ型に変換されます (たとえば `new Double(d).intValue()`)。 直接プリミティブ型の型変換を実行してください (たとえば `(int) d`)。 ### Bx: プリミティブ値が3項演算子のためにアンボクシングされて、型変換される (BX_UNBOXED_AND_COERCED_FOR_TERNARY_OPERATOR) ラップされたプリミティブ値は、3項演算子 (`b ? e1 : e2`) の評価の一部として、別のプリミティブ型にアンボクシングされて変換されます。 Java 言語仕様では、`e1` と `e2` がラップされた数値なら値はアンボクシングされ、共通の型へと変換/型変換されます (たとえば、`e1` が `Integer` で、`e2` が `Float` なら `e1` はアンボクシング (`int` に変換) され、`float` に変換され、ボクシング (`Float` に変換) されます)。 JLS セクション15.25を参照してください。 ### Bx: ボクシングされた値がアンボクシングされて、すぐに再ボクシングされる (BX_UNBOXING_IMMEDIATELY_REBOXED) ボクシングされた値がアンボクシングされて、すぐに再ボクシングされます。 ### Bx: プリミティブが比較でボクシングされている (DM_BOXED_PRIMITIVE_FOR_COMPARE) ボクシングされたプリミティブが単に compareTo メソッドを呼び出すために作られています。 直接プリミティブで働く static compare メソッド (double と　float は Java 1.4から、他のプリミティブ型は Java 1.7から) を使うほうがより効率的です。 ### Bx: ボクシング/アンボクシングはプリミティブを解析する (DM_BOXED_PRIMITIVE_FOR_PARSING) ボックス化されたプリミティブは、String から生成されていて、アンボックス化されたプリミティブ値を抽出します。 static parseXXX メソッドを呼び出す方が効率的です。 ### Bx: toString メソッドを呼び出すためにプリミティブ型のラッパクラスのインスタンスを作成している (DM_BOXED_PRIMITIVE_TOSTRING) `toString` メソッドを呼び出すためにプリミティブ型のラッパクラスのインスタンスを作成しています。 それよりもプリミティブ値を引数にとる static な `toString` メソッドを使用したほうが効率的です。
置換前 | 置換後
--- | ---
new Integer(1).toString() | Integer.toString(1)
new Long(1).toString() | Long.toString(1)
new Float(1.0).toString() | Float.toString(1.0)
new Double(1.0).toString() | Double.toString(1.0)
new Byte(1).toString() | Byte.toString(1)
new Short(1).toString() | Short.toString(1)
new Boolean(true).toString() | Boolean.toString(true)
> ### Bx: 効率が悪い浮動小数点 Number コンストラクタを呼び出しているメソッド (DM_FP_NUMBER_CTOR) `new Double(double)` の使用は、常に新しいブジェクトになることが保証されています。 これに対して、`Double.valueOf(double)` は、コンパイラ、クラスライブラリ、Java 仮想マシンで値がキャッシュされます。 キャッシュに格納された値を使用することはインスタンス生成を回避し、コードはより高速になります。 クラスが J2SE 5.0より前の Java 仮想マシンとの互換性が不要なら、オートボクシングか `Double`、`Float` の `valueOf` メソッドを使用してください。 ### Bx: 効率が悪い Number コンストラクタを呼び出しているメソッド (DM_NUMBER_CTOR) `new Integer(int)` の使用は、常に新しいブジェクトになることが保証されています。 これに対して、`Integer.valueOf(int)` は、コンパイラ、クラスライブラリ、Java 仮想マシンで値がキャッシュされます。 キャッシュに格納された値を使用することはインスタンスの作成を回避し、コードはより高速になります。 -128から127までの値は対応するキャッシュされたインスタンスを持つことが保証されています。 そして、`valueOf` メソッドの使用は、コンストラクタを使用するより約3.5倍高速です。 定数範囲外の値は、両方のスタイルの性能は同じです。 クラスが J2SE 5.0より前の Java 仮想マシンとの互換性が不要なら、`Long`、`Integer`、`Short`、`Character`、`Byte` のインスタンスを作成するときは、オートボクシングか `valueOf` メソッドを使用してください。 ### Dm: URL の equals メソッドと hashCode メソッドはブロックする (DMI_BLOCKING_METHODS_ON_URL) URL の `equals` メソッドと `hashCode` メソッドは、ドメイン名の解決を行うので、ひどい性能になる可能性があります。 詳細は、http://michaelscharf.blogspot.com/2006/11/javaneturlequals-and-hashcode-make.html を参照してください。 その代わりに `java.net.URI` を使用することを検討してください。 ### Dm: URL の Map や Set はひどい性能になる (DMI_COLLECTION_OF_URLS) このメソッドまたはフィールドは、URL の `Map` か `Set` を使用しています。 URL の `equals` と `hashCode` は、ドメイン名の解決を行うので、ひどい性能になります。 詳細は、http://michaelscharf.blogspot.com/2006/11/javaneturlequals-and-hashcode-make.html を参照してください。 その代わりに `java.net.URI` を使用することを検討してください。 ### Dm: 効率が悪い Boolean コンストラクタを呼び出しているメソッド (DM_BOOLEAN_CTOR) `java.lang.Boolean` の新しいインスタンスを作成するとメモリを浪費します。 `Boolean` オブジェクトは不変で、2つの有用な値 (`Boolean.TRUE` と `Boolean.FALSE`) があります。 その代わりに `Boolean.valueOf` メソッド (または J2SE 5.0 のオートボクシング) を使用して `Boolean` オブジェクトを作成してください。 ### Dm: 明示的なガベージコレクション (DM_GC) 明示的にガベージコレクションを呼び出しています。ベンチマークの特定の用途を除いて非常に疑わしいです。 過去に、`close` メソッドや `finalize` メソッドでガベージコレクタを明示的に呼び出していた状況は、巨大なパフォーマンスブラックホールの原因となりました。 ガベージコレクションは高くつきます。何百、何千ものガベージコレクションを強制する状況は、システムの停滞をもたらすでしょう。 ### Dm: クラスオブジェクトを得るためだけにインスタンスを作成しているメソッド (DM_NEW_FOR_GETCLASS) メソッドは、クラスオブジェクトを得るためにインスタンスを生成して `getClass` メソッドを呼び出しています。 クラスリテラル (`Foo.class`) を使うほうが簡単です。 ### Dm: 整数の乱数を生成するためには nextDouble メソッド ではなく nextInt メソッドを使用する (DM_NEXTINT_VIA_NEXTDOUBLE) `java.util.Random` のインスタンス `r` で、`0` から `n-1` の乱数を生成したいのであれば、`(int)(r.nextDouble() * n)` ではなく `r.nextInt(n)` を使用します。 `nextInt` メソッドへの引数は整数でなければなりません。 たとえば、-99から0までの乱数を生成したいなら、`-r.nextInt(100)` を使用してください。 ### Dm: 効率が悪い new String(String) コンストラクタを呼び出しているメソッド (DM_STRING_CTOR) `new String(String)` コンストラクタの使用はメモリを浪費します。 そのようにして構築されたオブジェクトと パラメータとして渡された `String` は機能的に区別がつかないからです。 引数の `String` をそのまま使用してください。 ### Dm: String の toString メソッドを呼び出しているメソッド (DM_STRING_TOSTRING) `String.toString()` を呼び出すのは冗長です。`String` を使用してください。 ### Dm: 効率が悪い new String() コンストラクタを呼び出しているメソッド (DM_STRING_VOID_CTOR) 引数がないコンストラクタを使用して、新しい `java.lang.String()` オブジェクトを作成するとメモリを浪費します。 そのようにして作成されたオブジェクトと空の文字列定数 `""` は機能的に区別がつかないからです。 Javaは、同一の文字列定数が同じ `String` オブジェクトによって表されることを保証します。 したがって、直接空の文字列定数を使用するべきです。 ### HSC: 複数のクラスファイルにわたって複製されている巨大な文字列定数 (HSC_HUGE_SHARED_STRING_CONSTANT) 巨大な文字列定数が複数のクラスファイルにわたって複製されています。 final フィールドが文字列定数で初期化され、Java 言語によって他のクラスからの final フィールドへのすべての参照がクラスファイルにインライン化されるからです。 JDK はこのバグを解決してサイズを1MB減らすことができました。 詳細は、JDK bug 6447475 を参照してください。 ### SBSC: ループの中で + を使用して文字列を連結しているメソッド (SBSC_USE_STRINGBUFFER_CONCATENATION) このメソッドは、ループの中で + を使用して `String` を構築していると思われます。 各々の繰り返しにおいて、`String` は `StringBuffer`/`StringBuilder` に変換、追加され、`String` へ変換されます。 各々の繰り返しで文字列が再コピーされ、増大すると繰り返しの数で二次コストの原因になる可能性があります。 `StringBuffer` (または J2SE 5.0の `StringBuilder`) を明示的に使うとより良い性能を得られます。 たとえば、
>     // This is bad
>     String s = "";
>     for (int i = 0; i < field.length; ++i) {
>         s = s + field[i];
>     }

>     // This is better
>     StringBuffer buf = new StringBuffer();
>     for (int i = 0; i < field.length; ++i) {
>         buf.append(field[i]);
>     }
>     String s = buf.toString();
### SIC: static 内部クラスにすべき (SIC_INNER_SHOULD_BE_STATIC) このクラスは内部クラスなのにそれを作成したオブジェクトへの埋め込まれた参照を使用していません。 この参照はより大きなクラスのインスタンスを作成して、必要以上に作成オブジェクトへの参照を存続しておくことがあります。 できれば、クラスは static にすべきです。 ### SIC: 名前付き static 内部クラスにリファクタリングできるかもしれない (SIC_INNER_SHOULD_BE_STATIC_ANON) このクラスは内部クラスなのにそれを作成したオブジェクトへの埋め込まれた参照を使用していません。 この参照はより大きなクラスのインスタンスを作成して、必要以上に作成オブジェクトへの参照を存続しておくことがあります。 できれば、クラスは static 内部クラスにすべきです。 無名内部クラスは static にできないので、名前付き内部クラスにリファクタリングする必要があります。 ### SIC: static 内部クラスにリファクタリングできるかもしれない (SIC_INNER_SHOULD_BE_STATIC_NEEDS_THIS) このクラスは内部クラスなのにそれを作成したオブジェクトへの埋め込まれた参照を使用していません。 この参照はより大きなクラスのインスタンスを作成して、必要以上に長く作成オブジェクトへの参照を存続しておくかもしれません。 できれば、クラスは static 内部クラスにすべきです。 外部オブジェクトへの参照が内部クラスのインスタンスを構築する間必要なので内部クラスのコンストラクタに外部インスタンスへの参照を渡すようにリファクタリングする必要があります。 ### SS: 読み出されないフィールド (SS_SHOULD_BE_STATIC) このクラスにはコンパイル時に静的な値に初期化されるインスタンス final フィールドがあります。 static フィールドにすることを検討してください。 ### UM: 定数値で Math クラスの static メソッドを呼び出しているメソッド (UM_UNNECESSARY_MATH) このメソッドは、定数値で `java.lang.Math` の static メソッドを呼び出しています。 このメソッドの結果は静的に判定でき、より高速で、ときには定数を使用するほうがより正確です。 検出されるメソッドは、以下のとおりです。
メソッド | パラメータ
--- | ---
abs | -any-
acos | 0.0 or 1.0
asin | 0.0 or 1.0
atan | 0.0 or 1.0
atan2 | 0.0
cbrt | 0.0 or 1.0
ceil | -any-
cos | 0.0
cosh | 0.0
exp | 0.0 or 1.0
expm1 | 0.0
floor | -any-
log | 0.0 or 1.0
log10 | 0.0 or 1.0
rint | -any-
round | -any-
sin | 0.0
sinh | 0.0
sqrt | 0.0 or 1.0
tan | 0.0
tanh | 0.0
toDegrees | 0.0 or 1.0
toRadians | 0.0
> ### UPM: private メソッドは決して呼び出されない (UPM_UNCALLED_PRIVATE_METHOD) この private メソッドは、決して呼び出されません。 メソッドがリフレクションによって呼び出されるかもしれないが、決して使われないなら除去するべきです。 ### UrF: 読み出されないフィールド (URF_UNREAD_FIELD) このフィールドは決して読み出されません。クラスから除去することを検討してください。 ### UuF: 未使用のフィールド (UUF_UNUSED_FIELD) このフィールドは決して使われません。クラスから除去することを検討してください。 ### WMI: entrySet イテレータではなく効率が悪い keySet イテレータを使用している (WMI_WRONG_MAP_ITERATOR) このメソッドは、keySet イテレータから取り出されたキーを使用して、マップエントリの値にアクセスしています。 Map の entrySet イテレータを使用したほうが `Map.get(key)` ルックアップを回避するのでより効率的です。 ### Dm: ハードコードされた定数データベースパスワード (DMI_CONSTANT_DB_PASSWORD) このコードは、ハードコードされた定数パスワードを使用してデータベース接続を作成しています。 ソースコードかコンパイルされたコードへアクセスできる人なら誰でも簡単にパスワードを知ることができてしまいます。 ### Dm: 空のデータベースパスワード (DMI_EMPTY_DB_PASSWORD) このコードは、空白または空のパスワードを使用してデータベース接続を作成しています。 これはデータベースがパスワードによって保護されていないことを示しています。 ### HRS: 信頼できない入力から形成された HTTP cookie (HRS_REQUEST_PARAMETER_TO_COOKIE) このコードは信頼できない HTTP パラメータを使用して HTTP クッキーを構築しています。 このクッキーが HTTP レスポンスに追加されるなら、HRS(HTTP レスポンススプリッティング) 脆弱性を可能にします。 詳細は、http://en.wikipedia.org/wiki/HTTP_response_splitting を参照してください。 FindBugs は、HRS の最も露骨で自明なケースだけを探します。 FindBugs が何かを発見したならほぼ間違いなく FindBugs が報告しないより多くの脆弱性があるでしょう。 HRS を心配するなら、商用の静的解析ツールかペネトレーションテストツールの使用を真剣に検討するべきです。 ### HRS: HTTP レスポンススプリッティング脆弱性 (HRS_REQUEST_PARAMETER_TO_HTTP_HEADER) このコードは、HTTP ヘッダに HTTP パラメータを直接書き込んでいます。これは HRS(HTTP レスポンススプリッティング) 脆弱性を可能にします。 詳細は、http://en.wikipedia.org/wiki/HTTP_response_splitting を参照してください。 FindBugs は、HRS の最も露骨で自明なケースだけを探します。 FindBugs が何かを発見したならほぼ間違いなく FindBugs が報告しないより多くの脆弱性があるでしょう。 HRS を心配するなら、商用の静的解析ツールかペネトレーションテストツールの使用を真剣に検討するべきです。 ### PT: サーブレットの絶対パストラバーサル (PT_ABSOLUTE_PATH_TRAVERSAL) ソフトウェアは、制限されたディレクトリ内にあるべきパス名を構築するためにHTTPリクエストのパラメータを使いますが、パラメータはそのディレクトリの外にある場所に解決できる「/abs/path」のような絶対パスシーケンスを適切に無効にしていません。 詳細は、http://cwe.mitre.org/data/definitions/36.html を参照してください。 FindBugs は、相対パストラバーサルの最も露骨で自明なケースだけを探します。 FindBugs が何かを発見したならほぼ間違いなく FindBugs が報告しないより多くの脆弱性があるでしょう。 相対パストラバーサルを心配するなら、商用の静的解析ツールかペネトレーションテストツールの使用を真剣に検討するべきです。 ### PT: サーブレットの相対パストラバーサル (PT_RELATIVE_PATH_TRAVERSAL) ソフトウェアは、制限されたディレクトリ内にあるべきパス名を構築するためにHTTPリクエストのパラメータを使いますが、パラメータはそのディレクトリの外にある場所に解決できる「..」のようなシーケンスを適切に無効にしていません。 詳細は、http://cwe.mitre.org/data/definitions/23.html を参照してください。 FindBugs は、相対パストラバーサルの最も露骨で自明なケースだけを探します。 FindBugs が何かを発見したならほぼ間違いなく FindBugs が報告しないより多くの脆弱性があるでしょう。 相対パストラバーサルを心配するなら、商用の静的解析ツールかペネトレーションテストツールの使用を真剣に検討するべきです。 ### SQL: SQL の Statement の execute または addBatch メソッドに定数でない文字列を渡している (SQL_NONCONSTANT_STRING_PASSED_TO_EXECUTE) このメソッドは、動的に生成されるように思われる文字列で、 SQL 文 の `execute` または `addBatch` メソッドを呼び出しています。 その代わりに `PreparedStatement` を使用することを検討してください。 効率的で、SQL インジェクション攻撃に強いです。 ### SQL: PreparedStatement が定数でない文字列から生成されている (SQL_PREPARED_STATEMENT_GENERATED_FROM_NONCONSTANT_STRING) このコードは、定数でない文字列から SQL の `PreparedStatement` を作成しています。 ユーザからのチェックされていない汚染されたデータがこの文字列を作る際に使われるなら、`PreparedStatement` で予想外で望ましくない何かをするために SQL インジェクションが使われる可能性があります。 ### XSS: 反射型クロスサイトスクリプティング脆弱性がある JSP (XSS_REQUEST_PARAMETER_TO_JSP_WRITER) このコードは、JSP の出力に HTTP パラメータを直接書き込んでいます。これは XSS(クロスサイトスクリプティング) 脆弱性を可能にします。 詳細は、http://en.wikipedia.org/wiki/Cross-site_scripting を参照してください。 FindBugs は、XSS の最も露骨で自明なケースだけを探します。 FindBugs が何かを発見したならほぼ間違いなく FindBugs が報告しないより多くの脆弱性があるでしょう。 XSS に関して心配しているなら商用の静的解析ツールかペネトレーションテストツールの使用を真剣に検討するべきです。 ### XSS: 反射型クロスサイトスクリプティング脆弱性がエラーページにあるサーブレット (XSS_REQUEST_PARAMETER_TO_SEND_ERROR) このコードは、サーブレットのエラーページに `HttpServletResponse.sendError` を使用して HTTP パラメータを直接書き込んでいます。 信頼できない入力を返すことは反射型 XSS(クロスサイトスクリプティング) 脆弱性を可能にします。 詳細は、http://en.wikipedia.org/wiki/Cross-site_scripting を参照してください。 FindBugs は、XSS の最も露骨で自明なケースだけを探します。 FindBugs が何かを発見したならほぼ間違いなく FindBugs が報告しないより多くの脆弱性があるでしょう。 XSS を心配するなら、商用の静的解析ツールかペネトレーションテストツールの使用を真剣に検討するべきです。 ### XSS: 反射型クロスサイトスクリプティング脆弱性があるサーブレット (XSS_REQUEST_PARAMETER_TO_SERVLET_WRITER) このコードは、サーブレットの出力に HTTP パラメータを直接書き込んでいます。これは反射型 XSS(クロスサイトスクリプティング) 脆弱性を可能にします。 詳細は、http://en.wikipedia.org/wiki/Cross-site_scripting を参照してください。 FindBugs は、XSS の最も露骨で自明なケースだけを探します。 FindBugs が何かを発見したならほぼ間違いなく FindBugs が報告しないより多くの脆弱性があるでしょう。 XSS を心配するなら、商用の静的解析ツールかペネトレーションテストツールの使用を真剣に検討するべきです。 ### BC: 抽象コレクションへの疑わしいキャスト (BC_BAD_CAST_TO_ABSTRACT_COLLECTION) このコードは、Collection を抽象コレクションにキャストしています (たとえば `List`、`Set`、`Map`)。 オブジェクトがキャストする型であるということが保証されていることを確認してください。 必要とするコレクションの反復処理ができるなら Set または List にキャストする必要はありません。 ### BC: 具象コレクションへの疑わしいキャスト (BC_BAD_CAST_TO_CONCRETE_COLLECTION) このコードは抽象コレクション (たとえば、Collection、List、Set) を特定の具象実装 (たとえば、ArrayList、HashSet) にキャストしています。 これは正しくないかもしれません。そして、将来の時点で他の具象実装への切り替えをとても困難にするので、脆弱なコードになるかもしれません。 そうするための特別な理由がないかぎり抽象コレクションクラスを使用してください。 ### BC: 未チェック/未確認のキャスト (BC_UNCONFIRMED_CAST) このキャストはチェックされていません。すべての型のインスタンスをキャストする型へキャストできるわけではありません。 プログラムのロジックがこのキャストが失敗しないことを確実に確認してください。 ### BC: メソッドからの戻り値の未チェック/未確認のキャスト (BC_UNCONFIRMED_CAST_OF_RETURN_VALUE) このコードは、メソッドの戻り値の未確認のキャストを実行しています。 コードは、キャストが安全であることが保証されるようにメソッドを呼び出しているかもしれませんが、FindBugs はキャストが安全であることを検証できません。 プログラムのロジックがこのキャストが失敗しないことを確実に確認してください。 ### BC: 常に true を返す instanceof (BC_VACUOUS_INSTANCEOF) この instanceof は常に true を返します (テストしている値が null でないかぎり)。 これは安全で、誤解や論理エラーを指摘していないことを確認してください。 本当に null なのか値をテストしたいなら、多分、instanceof ではなく null テストをしたほうが良く、より明確になります。 ### BSHIFT: 符号なし右シフトを short/byte にキャストしている (ICAST_QUESTIONABLE_UNSIGNED_RIGHT_SHIFT) このコードは、符号なしキャストの実行結果を short または byte にキャストしています。結果の上位ビットは捨てられます。 上位ビットが捨てられるので、符号付きと符号なし右シフト (シフトのサイズによって) との違いがないかもしれません。 ### CI: final なクラスが protected フィールドを宣言している (CI_CONFUSED_INHERITANCE) このクラスは、final と宣言されていますが、フィールドは protected と宣言されています。 クラスは fainal なので派生できません。、protected の使用は紛らわしいです。 フィールドのためのアクセス修飾子は、フィールドの真の用途を表すため、 private か public に変更するべきです。 ### DB: 2つの分岐のために同じコードを使用しているメソッド (DB_DUPLICATE_BRANCHES) このメソッドは、条件分岐の2つの分岐を実装するために同じコードを使用しています。これがコーディングミスではないことを確認してください。 ### DB: switch 文の2つの case のために同じコードを使用しているメソッド (DB_DUPLICATE_SWITCH_CLAUSES) このメソッドは、switch 文の2つの case を実装するために同じコードを使用しています。 複製コードの case かもしれないし、コーディングミスかもしれません。 ### DLS: ローカル変数への無効な代入 (DLS_DEAD_LOCAL_STORE) この命令はローカル変数に値を代入していますが、値は読み出されないか以降の命令でも使われません。 多くの場合、計算された値が決して使われないので、これは誤りを示します。 Sun の javac コンパイラが final なローカル変数のためにしばしば無効な格納を生成することに注意してください。 FindBugs は、バイトコードベースのツールなので誤検出をなくす簡単な方法がありません。 ### DLS: return 文に役に立たない代入がある (DLS_DEAD_LOCAL_STORE_IN_RETURN) この文は、return 文でローカル変数に代入をしています。この代入は効果がありません。 この文が正しいことを確かめてください。 ### DLS: ローカル変数への無効な null 代入 (DLS_DEAD_LOCAL_STORE_OF_NULL) このコードはローカル変数に null を代入していますが代入された値は読み出されていません。 この代入はガベージコレクタを手伝うために導入されたのかもしれませんが、Java SE 6 ではもはや必要とされないか有用ではありません。 ### DLS: フィールドを遮るローカル変数への無効な代入 (DLS_DEAD_LOCAL_STORE_SHADOWS_FIELD) この命令は、ローカル変数に値を代入していますが、値は読み出されないか以降の命令でも使われません。 多くの場合、計算された値が決して使われないので、これは誤りを示します。 フィールドがローカル変数と同じ名前です。そうではなく、フィールドに代入するつもりでしたか？ ### DMI: ハードコードされた絶対パス名への参照がある (DMI_HARDCODED_ABSOLUTE_FILENAME) このコードは、ハードコードされた絶対パス名を使用して File オブジェクトを構築しています (たとえば `new File("/home/dannyc/workspace/j2ee/src/share/com/sun/enterprise/deployment");`)。 ### DMI: ObjectOutput に書き込まれる非直列化可能オブジェクト (DMI_NONSERIALIZABLE_OBJECT_WRITTEN) このコードは、`ObjectOutput.writeObject` に非直列化可能オブジェクトを渡していると思われます。 このオブジェクトが本当に非直列化可能なら、エラーを招きます。 ### DMI: substring(0) の呼び出しは元の値を返す (DMI_USELESS_SUBSTRING) このコードは、文字列で `substring(0)` を呼び出していますが、元の値を返します。 ### Dm: Thread オブジェクトが Runnable が期待されているところに渡されている (DMI_THREAD_PASSED_WHERE_RUNNABLE_EXPECTED) Threadオブジェクトが Runnable が期待されているメソッドへのパラメータとして渡されています。 これはかなり異常で、論理エラーを示すか、予想外の振る舞いの原因になることがあります。 ### Eq: スーパークラスの equals メソッドをオーバーライドしていないクラス (EQ_DOESNT_OVERRIDE_EQUALS) このクラスは、`equals` メソッドを定義しているクラスを拡張してフィールドを追加していますが、`equals` メソッドを定義していません。 したがって、このクラスのインスタンスの等価性は、サブクラスと追加されたフィールドの同一性を無視します。 これが意図したことで、しかも、`equals` メソッドをオーバーライドする必要がないことを確実にしてください。 たとえ `equals` メソッドをオーバーライドする必要がないとしても、サブクラスのための `equals` メソッドが `super.equals(o)` を呼び出して結果を返すという事実を実証するためにいずれにしろ、`equals` メソッドをオーバーライドすることを検討してください。 ### Eq: 異常な equals メソッド (EQ_UNUSUAL) このクラスの `equals` メソッドは、引数の型が `this` オブジェクトの型と互換性があるこをチェックするために我々が認識しているパターンで何もしていません。 このコードは何も間違っていないかもしれませんが、レビューする価値があります。 ### FE: 浮動小数点の等価性のためのテスト (FE_FLOATING_POINT_EQUALITY) この演算は、等価性のために2つの浮動小数点値を比較しています。 浮動小数点の計算は丸めを伴うかもしれないので計算された float と double の値は正確ではないかもしれません。 通貨のような正確でなければならない値のために `BigDecimal` のような固定精度型を使用することを検討してください。 正確である必要がない値のためにいくつかの範囲の中で等価性のために比較することを検討してください。 たとえば、`if (Math.abs(x - y) < .0000001)`。 詳細は Java 言語仕様4.2.4を参照してください。 ### FS: Boolean 型でない引数を ％b 書式指示子を使用してフォーマットしている (VA_FORMAT_STRING_BAD_CONVERSION_TO_BOOLEAN) Boolean 型でない引数を %b 書式指示子でフォーマットしています。これは例外をスローしません。 その代わりに、非 null 値では true 、null では false を出力します。 書式文字列のこの機能は奇妙で意図したことではないかもしれません。 ### IA: 潜在的な継承されたメソッドなのか外部のメソッドなのかあいまいなメソッドの呼び出し (IA_AMBIGUOUS_INVOCATION_OF_INHERITED_OR_OUTER_METHOD) 内部クラスは、継承されたメソッドか外部クラスで定義されたメソッドなのかどちらとも解釈できるメソッドを呼び出しています。 たとえば、`foo(17)` を呼び出します。それはスーパークラスと外部のメソッドの両方で定義されています。 Java のセマンティックスでは、継承したメソッドを呼び出しますが、これはあなたが意図したことではないかもしれません。 本当に継承されたメソッドを呼び出すつもりなら super を付けて (例：super.foo(17)) 呼び出してください。 そうすれば、外部クラスのメソッドではなく継承されたメソッドを呼び出したいことがこのコードを読む人と FindBugs に明確になります。 `this.foo(17)` を呼び出す場合は、継承されたメソッドが呼び出されます。 しかしながら、FindBugs はクラスファイルを見るだけなので、`this.foo(17)` と `foo(17)` の呼び出しの違いを見分けることができません。 潜在的なあいまいな呼び出しについて文句を言うでしょう。 ### IC: 初期化が循環している (IC_INIT_CIRCULARITY) バグインスタンスによって参照される2つのクラスのスタティックイニシャライザで循環が検出されました。 さまざまな予想外の振る舞いはそのような循環に起因することがあります。 ### ICAST: 整数の除算の結果を double または float にキャストしている (ICAST_IDIV_CAST_TO_DOUBLE) このコードは 整数の除算の結果を double または float にキャストしています。 整数で除算をすることは、ゼロに最も近い整数値まで結果を切り捨てます。 結果が double にキャストされたという事実は、この精度が維持されるべきだったことを示唆しています。 おそらく意味されたことは、除算を実行する前にオペランドの1つまたは両方を double にキャストすることでした。 以下に例を示します。
>     int x = 2;
>     int y = 5;
>     // Wrong: yields result 0.0
>     double value1 =  x / y;

>     // Right: yields result 0.4
>     double value2 =  x / (double) y;
> ### ICAST: 整数乗算の結果を long にキャストしている (ICAST_INTEGER_MULTIPLY_CAST_TO_LONG) このコードは、以下のように整数の乗算を実行してから結果を long に変換しています。
>     long convertDaysToMilliseconds(int days) { return 1000*3600*24*days; }
> long を使用して乗算をすれば、結果がオーバーフローするという可能性を回避できます。 たとえば以下のように修正できます。
>     long convertDaysToMilliseconds(int days) { return 1000L*3600*24*days; }
> または
>     static final long MILLISECONDS_PER_DAY = 24L*3600*1000;
>     long convertDaysToMilliseconds(int days) { return days * MILLISECONDS_PER_DAY; }
> ### IM: 平均の計算はオーバーフローする可能性がある (IM_AVERAGE_COMPUTATION_COULD_OVERFLOW) このコードは、除算か符号付き右シフトを使用して2つの整数の平均を計算して、結果を配列の添字として使用しています。 平均値が非常に大きいならオーバーフローする可能性があります (結果として負の平均の計算になる)。 結果が負でないことを意図していたなら、その代わりに符号なし右シフトを使用できます。 つまり、`(low+high)/2` ではなく `(low+high) >>> 1` を使用してください。 このバグは、二分探索とマージソートの多くの以前の実装で存在します。 Martin Buchholz が JDK ライブラリのバグを発見して修正しています。 Joshua Bloch が バグパターンとして公表しました。 ### IM: 負数で機能しない奇数チェック (IM_BAD_CHECK_FOR_ODD) このコードは、`x % 2 == 1` を使用して値が負数なのか確かめていますが、負数 (たとえば、`(-5) % 2 == -1`) なので機能しません。 奇数チェックを意図しているなら、`x & 1 == 1` または `x % 2 != 0` を使用することを検討してください。 ### INT: 1を法とする整数の剰余 (INT_BAD_REM_BY_1) どんな式 `(exp % 1)` も常に0を返すことが保証されています。 そうではなく、`(exp & 1)` または `(exp & 2)` を意味していましたか？ ### INT: 整数値の無意味なビットマスク演算 (INT_VACUOUS_BIT_OPERATION) どんな有用な仕事もしない整数ビット演算 (AND、OR、XOR) です (たとえば `v & 0xffffffff`)。 ### INT: 整数値の無意味な比較 (INT_VACUOUS_COMPARISON) 常に同じ値を返す整数の比較があります (たとえば `x <= Integer.MAX_VALUE`)。 ### MTIA: Servlet クラスを拡張したクラスでのインスタンス変数の使用 (MTIA_SUSPECT_SERVLET_INSTANCE_FIELD) Servletクラスを拡張したクラスで、インスタンス変数を使用しています。 Servlet クラスの1つのインスタンスだけが Java EE フレームワークによって作成され、マルチスレッドによって使われるので、このパラダイムは極めて問題があり、推奨できません。 ローカル変数を使用することだけを検討してください。 ### MTIA: Struts Action を拡張したクラスでのインスタンス変数の使用 (MTIA_SUSPECT_STRUTS_INSTANCE_FIELD) Struts Action クラスを拡張したクラスで、インスタンス変数を使用しています。 Struts Action クラスの1つのインスタンスだけが Struts フレームワークによって作成され、マルチスレッドによって使われるので、このパラダイムは極めて問題があり、推奨できません。 ローカル変数を使用することだけを検討してください。 モニタを除いて書き込まれるインスタンスフィールドだけが報告されます。 ### NP: readLine メソッドの結果が null なのか確かめないで値を利用している (NP_DEREFERENCE_OF_READLINE_VALUE) `readLine` メソッドの結果が null なのか確かめないで値を利用しています。 `readLine` メソッドは、それ以上読み出すテキスト行がなければ null を返すので、NullPointerException が発生します。 ### NP: readLine メソッドの結果をすぐに利用している (NP_IMMEDIATE_DEREFERENCE_OF_READLINE) `readLine` メソッドの結果をすぐに利用しています。 `readLine` メソッドは、それ以上読み出すテキスト行がなければ null を返すので、NullPointerException が発生します。 ### NP: null とわかっている値のロード (NP_LOAD_OF_KNOWN_NULL_VALUE) ここで参照されている変数は、以前に null なのかチェックしているため null であることがわかっています。 これは有効ですが、間違いかもしれません (多分異なる変数を参照することを意図してました、または以前の null チェックで null でないのか確かめるべきでした)。 ### NP: メソッドはパラメータに nullness アノテーションを強化している (NP_METHOD_PARAMETER_TIGHTENS_ANNOTATION) メソッドは、オーバーライドするメソッドの契約を常に実装するべきです。 したがって、メソッドが @Nullable としてマークされるパラメーターを取るならば、サブクラスでパラメーターを @Nonnull にしてメソッドをオーバーライドするべきでありません。 そうするとメソッドが null パラメータを処理すべき契約を破ります。 ### NP: メソッドは戻り値の nullness アノテーションを緩和している (NP_METHOD_RETURN_RELAXING_ANNOTATION) メソッドは、オーバーライドするメソッドの契約を常に実装するべきです。 したがって、メソッドが @Nonnull 値を返すようにアノテートしているならば、サブクラスでメソッドが @Nullable または @CheckForNull 値を返すようにアノテートしてメソッドをオーバーライドするべきでありません。 そうするとメソッドが null を返すべできではない契約を破ります。 ### NP: null になっている可能性があるメソッドの戻り値を利用している (NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE) メソッドからの戻り値を null チェックしないで利用しています。メソッドの戻り値は null なのかチェックするべきです。 コードが実行されると NullPointerException を引き起こすことがあります。 ### NP: null 値を実行不可能かもしれない分岐で利用している可能性がある (NP_NULL_ON_SOME_PATH_MIGHT_BE_INFEASIBLE) 分岐または文が実行されるなら、null 値が利用されて NullPointerException が発生します。 もちろん、問題は分岐または文が実行不可能で、NullPointerException が決して発生する可能性がないということかもしれません。 それを決めるのは FindBugs の能力を超えています。 この値が既に null であることを検査したという事実からこれは明確な可能性です。 ### NP: パラメータは 非 null でなければならないが null 可能としてアノテートされている (NP_PARAMETER_MUST_BE_NONNULL_BUT_MARKED_AS_NULLABLE) このパラメータは、常に 非 null にすることを要求する方法で使われていますが、パラメータには明示的に null 可能としてアノテートされています。 パラメータかアノテーションのどちらかの使い方が間違っています。 ### NP: 書き込まれていない public または protected フィールドの読み出し (NP_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD) プログラムは、決して null 値でない値を書き込むと思われない public または protected フィールドの null 値を利用しています。 フィールドが解析によって見られない機構を通して初期化されないかぎり、この値を利用すると NullPointerException が発生します。 ### NS: 潜在的な非短絡論理の危険な使用 (NS_DANGEROUS_NON_SHORT_CIRCUIT) このコードは、短絡論理 (&& や ||) ではなく非短絡論理 (& や |) を使用していると思われます。 さらに、左辺値によって右辺を評価したくない (例外のスローや演算が高くつく副作用があるため) と思っているのかもしれません。 非短絡論理は、左辺を知ることによって結果を推論できたとしても両側の式が評価されます。 これは効率が悪く、右辺の評価でエラーが発生するケースを左辺でガードしているなら、結果としてエラーになる可能性があります。 詳細については、the Java Language Specification を参照してください。 ### NS: 非短絡論理の疑わしい使用 (NS_NON_SHORT_CIRCUIT) このコードは、短絡論理 (&& や ||) ではなく非短絡論理 (& や |) を使用していると思われます。 非短絡論理は、左辺を知ることによって結果を推論できたとしても両側の式が評価されます。 これは効率が悪く、右辺の評価でエラーが発生するケースを左辺でガードしているなら、結果としてエラーになる可能性があります。 詳細については、the Java Language Specification を参照してください。 ### PZLA: null ではなく長さが0の配列を返すことを検討する (PZLA_PREFER_ZERO_LENGTH_ARRAYS) 結果がないこと (すなわち、結果の空のリスト) を示すために null 参照ではなく長さが0の配列 を返すことは、多くの場合より良い設計です。 他方では、「この質問に対する答えがない」ことを示すために null を使用することはおそらく適切です。 たとえば、`File.listFiles()` は、ファイルがないディレクトリを与えられた場合は空のリストを返し、ファイルがディレクトリでないなら null を返します。 ### QF: 複雑か巧妙か間違ったインクリメントの for ループ (QF_QUESTIONABLE_FOR_LOOP) 本当にこの for ループが正しい変数をインクリメントしていますか？ 別の変数が for ループによって初期化されてチェックされるように見えます。 ### RCN: 非 null 値と null 値との冗長な比較 (RCN_REDUNDANT_COMPARISON_OF_NULL_AND_NONNULL_VALUE) このメソッドにはnull でないことがわかっている参照と null とわかっている別の参照との比較があります。 ### RCN: 2つの null 値の冗長な比較 (RCN_REDUNDANT_COMPARISON_TWO_NULL_VALUES) このメソッドには両方とも明らかに null とわかっている2つの参照の冗長な比較があります。 ### RCN: null でないことがわかっている値の冗長な null チェック (RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE) このメソッドには null でないことがわかっている値の冗長な null チェックがあります。 ### RCN: null とわかっている値の冗長な null チェック (RCN_REDUNDANT_NULLCHECK_OF_NULL_VALUE) このメソッドにはnull とわかっている値の冗長な null チェックがあります。 ### REC: 例外がスローされないのに例外をキャッチしている (REC_CATCH_EXCEPTION) このメソッドは、例外オブジェクトをキャッチする try-catch ブロックを使用していますが、例外は try ブロックの中でスローされません。また、実行時例外は明示的にキャッチされません。 それぞれの catch ブロックが同一である多くの例外型をキャッチすることの短縮形として `try { ... } catch (Exception e) { something }` を使用することが共通のバグパターンです。 しかし、この構文は誤って実行時例外も同様にキャッチするので、潜在的なバグを隠します。 より良いアプローチは、明示的にキャッチするよりもスローされる特定の例外をスローします。 あるいは、以下に示すように明示的に RuntimeException をキャッチ、再スローして、非実行時例外をキャッチします。
>     try {
>         ...
>     } catch (RuntimeException e) {
>         throw e;
>     } catch (Exception e) {
>         ... deal with all non-runtime exceptions ...
>     }
> ### RI: スーパークラスと同じインタフェースを実装しているクラス (RI_REDUNDANT_INTERFACES) このクラスは、スーパークラスによっても実装されるインタフェースを実装することを宣言しています。 スーパークラスがインタフェースを実装するので、これは冗長です。デフォルトですべてのサブクラスもこのインタフェースを実装します。 このクラスが作成されてから継承階層が変わったことを指摘するかもしれません。インタフェースの実装の所有権を考慮するべきです。 ### RV: String.indexOf の結果が正かどうか確かめている (RV_CHECK_FOR_POSITIVE_INDEXOF) このメソッドは `String.indexOf` を呼び出して結果が正かどうか確かめています。 結果が負かどうか確かめるほうがずっと典型的です。チェックされる部分文字列が先頭以外の場所で出現するときだけ正になります。 ### RV: readLine メソッドの結果を null でないのか確かめた後で捨てている (RV_DONT_JUST_NULL_CHECK_READLINE) `readLine` メソッドの戻り値を null でないのか確かめた後で捨てています。 ほとんどすべての状況で、結果が null でないなら戻り値を使用したいでしょう。 再び `readLine` メソッドを呼び出すと異なる行が得られます。 ### RV: ハッシュコードの剰余は負かもしれない (RV_REM_OF_HASHCODE) このコードは、ハッシュコードを計算して別の値を法とする剰余を計算しています。 ハッシュコードは負になり、剰余演算の結果も負なります。 計算結果が負ではないことを確認したいなら、コードを変更する必要があるかもしれません。 除数が2の累乗であることがわかっているなら、代わりにビット演算を使用できます (すなわち、`x.hashCode()%n` の代わりに `x.hashCode()&(n-1)` を使用してください)。 これはおそらく、剰余を計算するより高速です。 除数が2の累乗であるということをわかっていないなら、剰余演算の結果の絶対値を取得してください (すなわち `Math.abs(x.hashCode()%n)`)。 ### RV: 符号付き32ビット整数の乱数の剰余 (RV_REM_OF_RANDOM_INT) このコードは符号付き整数の乱数を生成して別の値を法とする剰余を計算しています。 乱数は負になり、剰余演算の結果も負になります。これが意図したことであることを確実にしてください。 その代わりに `Random.nextInt(int)` の使用を強く検討してください。 ### RV: メソッドは戻り値を無視しています、これは間違いではないですか? (RV_RETURN_VALUE_IGNORED_INFERRED) このコードは、メソッドを呼び出して、戻り値を無視しています。 戻り値は、メソッドが呼び出される型と同じ型です。そして、我々の解析から戻り値が重要であるかもしれないように見えます （たとえば、`String.toLowerCase()` の戻り値を無視するような）。 我々は、戻り値を無視することがメソッド本体の単純な解析から悪い考えかもしれないと推測しています。 このメソッドの戻り値を無視することが重要であるか許容できるかどうかに関して、FindBugs に指示する @CheckReturnValue アノテーションが使えます。 戻り値を無視することが間違いではないか決めるために厳密に調査してください。 ### RV: 副作用がないメソッドの戻り値は無視される (RV_RETURN_VALUE_IGNORED_NO_SIDE_EFFECT) このコードは、メソッドを呼び出して戻り値を無視しています。 しかしながら、解析はメソッド (もしあればサブクラスの実装も含む) が戻り値以外の効果をもたらさないことを示しています。 この呼び出しは除去できます。 我々は、できる限り誤検出を減らそうとしていますが、いくつかのケースではこの警告が間違っているかもしれません。 よくある誤検出です。 - メソッドは、オーバライドされ解析対象外の他のプロジェクトで副作用がもたらされるように設計されている - メソッドは、副作用をもたらすかもしれないクラスローダをトリガーするように呼び出されている - メソッドは、例外を取得するために呼び出されている 我々の仮定が正しくないと感じるなら、FindBugs にこのメソッドの戻り値が無視されることを許容するように指示する @CheckReturnValue アノテーションを使用することができます。 ### SA: フィールドの二重代入 (SA_FIELD_DOUBLE_ASSIGNMENT) このメソッドにはフィールドの二重代入があります。 たとえば以下のようなコードです。
>     int x,y;
>     public void foo() {
>         x = x = 17;
>     }
> フィールドに2回代入することは役に立たないので、論理エラーかタイプミスかもしれません。 ### SA: ローカル変数の二重代入 (SA_LOCAL_DOUBLE_ASSIGNMENT) このメソッドにはローカル変数の二重代入があります。 たとえば以下のようなコードです。
>     public void foo() {
>         int x,y;
>         x = x = 17;
>     }
> 変数に同じ値を2回代入することは役に立たないので、論理エラーかタイプミスかもしれません。 ### SA: ローカル変数の自己代入 (SA_LOCAL_SELF_ASSIGNMENT) このメソッドにはローカル変数の自己代入があります。 たとえば以下のようなコードです。
>     public void foo() {
>         int x = 3;
>         x = x;
>     }
> そのような代入は役に立たないので、論理エラーかタイプミスかもしれません。 ### SF: 1つの case が次の case へと通り抜ける switch 文を発見した (SF_SWITCH_FALLTHROUGH) このメソッドには1つの case が次の case へと通り抜ける switch 文があります。 通常は、break か return でこの case を終わらせる必要があります。 ### SF: default がない switch 文を発見した (SF_SWITCH_NO_DEFAULT) このメソッドにはdefault がない switch 文があります。 通常は、default を用意する必要があります。 解析は生成されたバイトコードを見るだけなので、default が switch 文の終わりにあって、他のケースに break 文が含まれていないなら誤検出のトリガーとなります。 ### ST: インスタンスメソッドから static フィールドへの書き込み (ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD) このインスタンスメソッドは、static フィールドに書き込みをしています。 複数のインスタンスが操作されているなら、正しくさせるのは難しいです。一般的にバッドプラクティスです。 ### Se: サブクラスで継承できない private な readResolve メソッド (SE_PRIVATE_READ_RESOLVE_NOT_INHERITED) このクラスは、private な `readResolve` メソッドを定義しています。 そのため、このメソッドはサブクラスで継承できません。 これが意図したことなら間違っていないかもしれませんが確認するためにレビューするべきです。 ### Se: Serializable でないクラスの transient フィールド (SE_TRANSIENT_FIELD_OF_NONSERIALIZABLE_CLASS) フィールドは、transient と宣言していますが、クラスは直列化可能ではないので、まったく効果がありません。 クラスが transient だったときの名残かもしれません、または直列化機構を誤解しているのかもしれません。 ### TQ: 値は型修飾子を必要としているが、不明としてマークされている (TQ_EXPLICIT_UNKNOWN_SOURCE_VALUE_REACHES_ALWAYS_SINK) 値は、常に型修飾子によって示された値であることを必要とする方法で使われています。 しかし、値はどこでその型修飾子が必要なのかわからないと述べている明示的なアノテーションがあります。 使い方かアノテーションのどちらかが間違っています。 ### TQ: 値は型修飾子を必要としないが、不明としてマークされている (TQ_EXPLICIT_UNKNOWN_SOURCE_VALUE_REACHES_NEVER_SINK) 値は、型修飾子によって示された値でないことを必要とする方法で使われています。 しかし、値はどこでその型修飾子がいるのか禁止されていのるかわからないと述べている明示的なアノテーションがあります。 使い方かアノテーションのどちらかが間違っています。 ### UC: 条件は効果がない (UC_USELESS_CONDITION) この条件は常に関係している変数の値が前に絞られたのと同じ結果を作り出します。 おそらく何かほかのことを意味していたのか、あるいは条件を除去できます。 ### UC: 条件は変数型のために効果がない (UC_USELESS_CONDITION_TYPE) この条件は関係している変数の型範囲のために常に同じ結果を作り出します。 おそらく何かほかのことを意味していたのか、あるいは条件を除去できます。 ### UC: 役に立たないオブジェクトを作成した (UC_USELESS_OBJECT) 我々の解析でオブジェクトが役に立たないことを示しています。 作成され、変更されていますが、値はメソッドの外に出ないし、副作用をもたらしません。 間違いかオブジェクトが使われることを意図していたかのどちらか、あるいは除去できます。 この解析はめったに誤検出することはありません。よくある誤検出のケースです。 - 暗黙のうちに曖昧な例外をスローした - コードを一般化してスタブとして使用された - 弱/ソフト参照オブジェクトへの強い参照を持っていた ### UC: 役に立たないオブジェクトをスタックで作成した (UC_USELESS_OBJECT_STACK) このオブジェクトは副作用を持たない修正を行うために作成されています。 おそらく何かほかのことを意味していたのか、あるいはオブジェクトを除去できます。 ### UC: 役に立たない空ではない void メソッド (UC_USELESS_VOID_METHOD) 我々の解析は、この空ではない void メソッドが実際に有用な仕事を行わないことを示しています。 確認してください。おそらくそのコードが間違っているか、またはボディを完全に除去できます。 我々はできる限り誤検出を減らそうと努力しているが、いくつかのケースでは警告は間違っているかもしれません。 よくある誤検出例です。 - メソッドは、副作用を持つかもしれないクラスのロードをトリガすることを意図している - メソッドは、暗黙のわかりにくい例外をスローするように意図されている ### UCF: 役に立たない制御フロー (UCF_USELESS_CONTROL_FLOW) このメソッドには分岐するのかどうかに関係なく、制御フローが同じ場所へと続く、役に立たない制御フロー文があります。 たとえば、これは 空の `if` 文が原因になります。
>     if (argv.length == 0) {
>         // TODO: handle this case
>     }
> ### UCF: 次の行へ続くだけの役に立たない制御フロー (UCF_USELESS_CONTROL_FLOW_NEXT_LINE) このメソッドには分岐するのかどうかに関係なく、制御フローが同じか次の行へと続く、役に立たない制御フロー文があります。 多くの場合、不注意に `if` 文の本体を空文を使用したことが原因になります。
>     if (argv.length == 1);
>         System.out.println("Hello, " + argv[0]);
### UrF: 読み出されない public または protected フィールド (URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD) このフィールドは決して読み出されません。 フィールドは、public か protected なので、多分、それは解析の一部として見えないクラスで使用されることを意図しています。 そうでなければ、クラスから除去することを検討してください。 ### UuF: 未使用の public または protected フィールド (UUF_UNUSED_PUBLIC_OR_PROTECTED_FIELD) このフィールドは決して使用されません。 フィールドは、public か protected なので、多分、それは解析の一部として見えないクラスで使用されることを意図しています。 そうでなければ、クラスから除去することを検討してください。 ### UwF: コンストラクタで初期化されていないフィールドを null チェックなしで null 値を利用している (UWF_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR) このフィールドは、どんなコンストラクタの中でも決して初期化されません。したがって、オブジェクトが構築された後、null である可能性があります。 どこかほかで、値がロードされて、null チェックなしで null 値が利用されます。 フィールドが初期化される前に利用されると NullPointerException が発生するので、誤りか疑わしい設計かもしれません。 ### UwF: 書き込まてれいない public または protected フィールド (UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD) この public または protected フィールドは書き込まれていません。このフィールドからの読み出しはデフォルト値を返します。 誤りをチェックしてください (フィールドは初期化するべきでしたか？)。役に立たないなら除去してください。 ### XFB: XMLインタフェースの特定の実装のインスタンスを作成しているメソッド (XFB_XML_FACTORY_BYPASS) このメソッドは、XMLインタフェースの特定の実装のインスタンスを作成しています。 提供されたファクトリクラスを使用してオブジェクトを作成して実行時に実装を変更できるようにすることが望ましいです。 詳細は、以下を参照してください。 javax.xml.parsers.DocumentBuilderFactory javax.xml.parsers.SAXParserFactory javax.xml.transform.TransformerFactory org.w3c.dom.Document.createXXXX Send comments to findbugs@cs.umd.edu