1. ホーム
  2. Java

FindBugの使用概要

2022-02-11 10:39:46

AM : 空の jar ファイルエントリーを作成します (AM_CREATES_EMPTY_JAR_FILE_ENTRY)
putNextEntry()からcloseEntry()までの間、jarファイルに対して他の操作は一切行いません。これにより、jar ファイルに空のエントリが生成されます。
このコードでは、putNextEntry()を呼び出し、その直後にcloseEntry()を呼び出しています。エントリの内容は、putNextEntry() と closeEntry() の呼び出しの間に、JarFile に書き込まれる必要があります。
AM : 空の ZIP ファイルエントリを作成します (AM_CREATES_EMPTY_ZIP_FILE_ENTRY).
putNextEntry() と closeEntry() の間、zip ファイルに対して他の操作は行われません。これにより、ZIP ファイルに空のエントリが生成されます。
このコードでは、putNextEntry()を呼び出し、その直後にcloseEntry()を呼び出しています。エントリーの内容は、putNextEntry() と closeEntry() の呼び出しの間に ZipFile に書き込まれるべきものです。
BC : Equals メソッドは、引数の型について何も仮定してはいけません (BC_EQUALS_METHOD_SHOULD_WORK_FOR_ALL_OBJECTS).
equalsメソッドでは、パラメータの型一致判定が行われていません。変更は簡単で、追加します。
if (! (o instanceof [現在のクラス]) { ... <未定義
は false を返します。
}
equals(Object o)メソッドはoの型を仮定してはいけません。oがこれと同じ型でない場合、単にfalseを返すべきです。
BC : ランダムに生成され、一度だけ使用されるオブジェクト (DMI_RANDOM_USED_ONLY_ONCE)
java.util.Randomオブジェクトは、乱数を生成するために一度だけ使用され、その後破棄されます。通常は、このオブジェクトを保存しておき、乱数を使用する必要があるときはいつでもこのオブジェクトを呼び出すようにします。
Random オブジェクトを使用して乱数を 1 つ生成し、Random オブジェクトを破棄します。可能であれば、Randomオブジェクトを一度生成して保存し、新しい乱数が必要になるたびに既存のRandomオブジェクトのメソッドを呼び出すようにコードを書き換えてください。 可能であれば、Randomオブジェクトを一度生成して保存し、新しい乱数が必要になるたびに既存のRandomオブジェクトのメソッドを呼び出して乱数を取得するようにコードを書き換えてください。
BIT : ビット演算の符号をチェックする (BIT_SIGNED_CHECK)
ビット演算を使用し、>0 の比較を行う判定文。例えば、以下のようなものです。
((event.detail & SWT.SELECTED) > 0)
この判定は、2つの数値のwith演算後に残る0でないビットの数であるとされている。しかし、不用意にwith演算を行うと負の数になってしまい、バグとなる。このため、"! ="を">0"に置き換えるのがよいでしょう。
このメソッドは、次のような式を比較します。
((event.detail & SWT.SELECTED) > 0)
. ビット演算を使ってから大なり小なり比較すると、(もちろんSWTの値にもよりますが)予期せぬ結果になることがあります。SWT.SELECTEDが負の数であれば、これはバグの候補になります。SWT.SELECTEDが負でない場合でも、「> 0」ではなく「! = 0」を使うのが良さそうです。
ボリス・ボコウスキー


CN : クラスは Cloneable を実装しているが、clone メソッドを定義または使用していない(CN_IDIOM)
あるクラスは Cloneable インターフェースを実装していますが、clone メソッドを宣言していませんし、使用してもいません。clone メソッドは Object クラスのメソッドなので、メソッドを宣言しなくても現在のクラスはコンパイルに失敗することはない。しかし、cloneはフィールド単位でコピーする必要があるため、cloneメソッドを宣言しないのは誤りです。
Cloneable を実装しているが、clone メソッドを定義しない、または使用しないクラス。
CN : clone メソッドが super.clone() を呼び出さない(CN_IDIOM_NO_SUPER_CALL)
clone() メソッドを定義しているが、メソッド内で super.clone() を呼び出していない非終端クラス。
super.clone()は呼ばない方がいいようです。A が B の親で、B が super.clone() を呼び出した場合、B の clone メソッドは A のインスタンスを返しますが、これは間違っているように見えます。
しかし、すべての clone() メソッドが super.clone() を呼び出す場合、最後の呼び出しは Object.clone() になり、正しい型が返されます。
この非最終クラスは、super.clone()を呼び出さないclone()メソッドを定義しています。このクラス ("A") がサブクラス ("B") によって拡張され、サブクラス B が super.clone() を呼び出した場合、B の clone() メソッドは A タイプのオブジェクトを返す可能性があり、これは clone() に対する標準契約に違反します。
すべての clone() メソッドが super.clone() を呼び出す場合、それらは Object.clone() を使用することが保証され、常に正しい型のオブジェクトが返されます。

CN : クラスは clone() を定義しているが、Cloneable を実装していない (CN_IMPLEMENTS_CLONE_BUT_NOT_CLONEABLE)
このクラスは clone() メソッドを定義していますが、Cloneable インターフェースを実装していることを宣言していません。これは大きな問題ではなく、宣言が欠落していないことを確認するだけです。
このクラスは clone() メソッドを定義していますが、Cloneable を実装していません。これが問題ない状況もありますが (たとえば、サブクラスが自分自身をクローンする方法を制御したい場合など)、これが意図したものであることを確認してください。
Co : 抽象クラスが共変量 compareTo() メソッドを定義している(CO_ABSTRACT_SELF)
クラスは、Object 型でないパラメータを持つ compareTo() メソッドを定義しています。Comparable インターフェイスの compareTo() メソッドを適切に実装するためのベストプラクティスは、compareTo() メソッドの引数が Object クラスであることです。
このクラスは、compareTo()の共変化版を定義します。Comparable インターフェースの compareTo() メソッドを正しくオーバーライドするために、 compareTo() のパラメータは java.lang.Model 型である必要があります。
Co : Covariant compareTo() メソッド定義(CO_SELF_NO_OBJECT)
<スパン 同上
このクラスは、compareTo()の共変化版を定義します。Comparable インターフェースの compareTo() メソッドを正しくオーバーライドするために、 compareTo() のパラメータは java.lang.Model 型である必要があります。
DE : メソッドが落ちるかもしれない例外(DE_MIGHT_DROP)
このメソッドは例外を取りこぼした可能性があります。通常の場合、例外は何らかの方法で処理されるか、報告されるか、外層に投げ返されるはずです。
このメソッドは例外を発生させる可能性があります。一般に、例外は何らかの方法で処理するか報告するか、あるいはメソッドから throw out されるべきです。
DE : メソッドが例外を無視する可能性がある(DE_MIGHT_IGNORE)
このメソッドは、おそらく例外を無視します。通常の場合、例外は何らかの方法で処理されるか、報告されるか、外層に投げ返されるはずです。
このメソッドは例外を無視することがあります。一般に、例外は何らかの方法で処理するか報告するか、あるいはメソッドから throw out されるべきです。
DMI : コレクションをクリアするのに removeAll を使用しない(DMI_USING_REMOVEALL_TO_CLEAR_COLLECTION)
コレクション内のすべての要素を削除したい場合は、c.removeAll( c )メソッドではなく、コレクションのclearメソッドを使用します。c.removeAll( c ) を呼び出してコレクションをクリアすると、きれいにクリアされず、エラーが発生しやすく、ConcurrentModificationExceptionがスローされる可能性があります。
コレクションcからすべての要素を削除したい場合は、c.removeAll(c)ではなく、c.clearを使用します。コレクションをクリアするために c.removeAll(c) を呼び出すと、明確でなく、タイプミスによるエラーの影響を受けやすく、効率が悪く、コレクションによっては ConcurrentModificationException をスローする可能性があります。
DP : クラスローダーは doPrivileged ブロックの内部でのみ作成する必要があります (DP_CREATE_CLASSLOADER_INSIDE_DO_PRIVILEGED).
このコードは、セキュリティマネージャを必要とするクラスローダを書いています。もし、コードが安全として承認される必要があるが、安全でないコードによって呼び出される可能性がある場合、クラスローダはdoPrivilegedブロック内に配置される必要があります。
このコードはクラスローダを作成するもので、セキュリティマネージャを必要とします。もし、このコードがセキュリティパーミッションを与えられているが、セキュリティパーミッションを持たないコードから起動される可能性がある場合、クラスローダーの作成は doPrivileged ブロックの内部で行う必要があります。

DP : doPrivileged ブロックの内部でのみ実行されるべきメソッドが呼び出された (DP_DO_INSIDE_DO_PRIVILEGED)

このコードは、セキュリティ権限チェックを必要とするメソッドを呼び出すものです。もしそのコードがセキュリティパーミッションの認証を必要とするが、安全でないコードから呼び出される可能性がある場合、クラスローダーをdoPrivilegedブロックの中に配置する必要があります。
このコードは、セキュリティ権限チェックを必要とするメソッドを呼び出すものです。このコードがセキュリティパーミッションを付与されるが、セキュリティパーミッションを持たないコードによって呼び出される可能性がある場合、このコードはdoPrivilegedブロックの内部で呼び出されることが必要です。
Dm : System.exit(...)を呼び出すメソッド (DM_EXIT)
System.exitは、VMプロセスをシャットダウンするために呼び出されます。これは適切な場合にのみ使用してください。この呼び出しによって、あなたのコードが他のコードから呼び出されることが不可能ではないにしても、困難になります。代わりにRuntimeExceptionを投げる方がよいでしょう。
System.exitを起動すると、Java仮想マシン全体がシャットダウンされます。これは、適切な場合にのみ実行されるべきです。代わりに RuntimeException を投げることを検討してください。
Dm : 危険なメソッド runFinalizersOnExit(DM_RUN_FINALIZERS_ON_EXIT) を起動する。
System.runFinalizersOnExit や Runtime.runFinalizersOnExit は、いかなる理由であれ、決して呼び出さないようにしてください。
<スパン -- Javaの名付け親であるJoshua Bloch氏
どんな理由であれ、System.runFinalizersOnExit や Runtime.runFinalizersOnExit は絶対に呼ばないでください。-- ジョシュア・ブロッホ
ES : または! =(ES_COMPARING_PARAMETER_STRING_WITH_EQ) による文字列パラメータの比較
このコードでは、文字列の比較に == や ! = を使っています。この文字列の比較方法は、同じ内容の文字列を比較するのではなく、同じオブジェクトであるかどうかで比較します。この比較は、equalsメソッドで置き換えることができます。
このコードでは、java.lang.String パラメータを == または ! = 演算子で参照等価性を比較します。メソッドに String 定数または内部文字列のみを渡すことを呼び出し元に要求することは不必要に脆弱であり、測定可能な結果をもたらすことはほとんどありません。 代わりに equals(Object) メソッドを使用します。
ES : または! =(ES_COMPARING_STRINGS_WITH_EQ) を用いた文字列オブジェクトの比較
<スパン 同上
このコードでは、java.lang.String オブジェクトを == または ! = 演算子で参照して等価かどうかを比較します。両方の文字列がソースファイル内の定数であるか、または String.intern() メソッドでインターンされていない限り、同じ文字列値が2つの異なる String オブジェクトで表現される可能性があります。代わりにequals(Object)メソッドを使用することを検討してください。
Eq : 抽象クラスが共変量 equals() メソッドを定義する(EQ_ABSTRACT_SELF)
このクラスはequals()メソッドを定義していますが、引数はObjectのサブクラスです。equals()メソッドを正しくオーバーライドするには、引数はObjectでなければなりません。
このクラスは,equals()の共変化版を定義する。java.lang.Object の equals() メソッドを正しくオーバーライドするためには, equals() のパラメータが java.lang.Object 型である必要があります.
Eq : Equals は互換性のないオペランドをチェックします (EQ_CHECK_FOR_OPERAND_NOT_COMPATIBLE_WITH_THIS).
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メソッドは、引数が何らかの互換性のない型(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(...) メソッドを定義していますが、Object の equals() メソッドを直接継承しています。通常、compareToメソッドはequalsメソッドがtureを返す場合にのみ0を返しますが、この原則に従わない場合、奇妙で予測不可能な問題が発生します。java5では、PriorityQueue.removeメソッドはcompareToメソッドを使用していますが、java6ではequalsメソッドを使用しています。
<スパン これ以上、言う必要はないでしょう。
このクラスは compareTo(...) メソッドを定義していますが、equals() メソッドは java.lang から継承しています。一般に、compareToの値は、equalsがtrueを返す場合のみ、0を返すべきです。これに違反すると、PriorityQueueのようなクラスで奇妙で予測不可能な失敗が発生します。Java 5 では PriorityQueue.remove メソッドは compareTo メソッドを使用し、Java 6 では equals メソッドを使用しています。
ComparableインターフェイスのcompareToメソッドのJavaDocより。
(x.compareTo(y)==0) == (x.equals(y)) であることが強く推奨されますが、厳密には必須ではありません。一般に、Comparable インターフェースを実装し、この条件に違反するクラスは、この事実を明確に示す必要があります。言語は "Note: このクラスは equals." と矛盾する自然順序を持っています。

Eq : equals メソッドが subtypes(EQ_GETCLASS_AND_CLASS_CONSTANT) で失敗する。
このクラスは独自のequalsメソッドを書いていますが、このメソッドは引数のオブジェクト型を比較する際に継承不可と定義されており、サブクラスがこのクラスを継承した場合、エラーになります。例えば、Fooクラスのチェックは
if (Foo.class == o.getClass()). に変更したほうがよさそうです。
if (this.getClass() == o.getClass())
このクラスには、サブクラスに継承されると壊れてしまうequalsメソッドがあります。これはクラスリテラルと引数のクラスを比較します(例えば、Fooクラスでは、Foo.class == o.getClass()かどうかをチェックします)。this.getClass() == o.getClass()であるかどうかをチェックする方がよいでしょう。
Eq : Covariant equals() メソッド defined(EQ_SELF_NO_OBJECT)
equals()メソッドの引数は、理想的にはObjectであるべきです。そうでない場合は、問題が発生しやすくなります。
このクラスは,equals()の共変化版を定義する。java.lang.Object の equals() メソッドを正しくオーバーライドするためには, equals() のパラメータが java.lang.Object 型である必要があります.