16

私が取り組んでいるシステムに次の(ドクターされた)クラスがあり、 FindbugsがSE_BAD_FIELD警告を生成しています。私が思った方法で修正する前に、なぜそれが表示されるのかを理解しようとしています。私が混乱している理由は、説明がクラスで他のシリアル化できないインスタンスフィールドを使用していないことを示しているように見えるためですが、bar.model.Fooもシリアル化できず、まったく同じ方法で使用されています(私がわかります)が、Findbugsは警告を生成しません。

import bar.model.Foo;

import java.io.File;
import java.io.Serializable;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Demo implements Serializable {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());
    private final File file;
    private final List<Foo> originalFoos;
    private Integer count;
    private int primitive = 0;

    public Demo() {
        for (Foo foo : originalFoos) {
            this.logger.debug(...);
        }
    }

    ...

}

解決策での私の最初の赤面は、私がそれを使用するときに、工場からロガー参照を取得することです。

public DispositionFile() {
    Logger logger = LoggerFactory.getLogger(this.getClass());
    for (Foo foo : originalFoos) {
        this.logger.debug(...);
    }
}

ただし、これは特に効率的ではないようです。

考え?

4

5 に答える 5

19

まず、時期尚早に最適化しないでください。それはLoggerFactory.getLogger()十分に高速であり、実行時間に大きなオーバーヘッドを与えない可能性があります。疑わしい場合は、プロファイルを作成してください。

第二に、findbugsがの使用について不平を言ってFooいない理由は、クラスにタイプのフィールドがなく、タイプのフィールドがあるためFooですList。ジェネリックはコンパイル時に消去されますFoo。フィールド定義に関する限り、クラス内での実際の参照はありません。実行時に、シリアル化できないという事実Fooは、クラスのインスタンスをシリアル化しようとした場合に例外を引き起こしますがDemo、findbugsはこれを知ることができません。

私の最初の反応はLogger、インスタンスフィールドではなく、静的フィールドを作成することです。この状況では正常に動作するはずです。

public class Demo implements Serializable {
   private static final Logger logger = LoggerFactory.getLogger(Demo.class);

   // .. other stuff
}
于 2010-05-10T21:25:38.537 に答える
7

私は物事が正接して離陸したくないのですが、ロガーの従来の初期化を検討しましたか?

private static final Logger logger = LoggerFactory.getLogger(Demo.class);

インスタンスごとに異なるロガーが実際に必要ない場合(これは珍しいことです)、問題は解決します。

ちなみに、SL4Jの作者は( commons-loggingのようなLog4Jラッパーの批評で)言った、

多くの場合、これらのラッパーの品質は疑わしいため、非アクティブな(または無効にされた)ログステートメントのコストは、log4jを直接使用する場合と比較して1,000倍(1,000)倍になります。ラッパークラスで最も一般的なエラーは、各ログリクエストでのLogger.getLoggerメソッドの呼び出しです。これは、アプリケーションのパフォーマンスに大きな打撃を与えることが保証されています。本当に!!!

これは、必要になるたびにロガーを取得するという別のアイデアは推奨されないことを示唆しています。

于 2010-05-10T21:33:03.580 に答える
6

org.slf4j.Loggerインターフェースがjava.io.Serializableとしてマークされていないため、この特定のケースではFindBugsが誤解を招きます。ただし、SLF4Jに同梱されているSLF4Jロガーの実装はすべて、すぐに使用できるシリアル化をサポートしています。それを試してみてください。あなたはそれが機能するのを見るでしょう。

SLF4jFAQからの抜粋は次のとおりです。

静的変数とは異なり、インスタンス変数はデフォルトでシリアル化されます。SLF4Jバージョン1.5.3の時点で、ロガーインスタンスはシリアル化後も存続します。したがって、ロガーがインスタンス変数として宣言されている場合でも、ホストクラスのシリアル化に特別なアクションは必要ありません。以前のバージョンでは、ロガーインスタンスをホストクラスで一時的なものとして宣言する必要がありました。

http://slf4j.org/faq.html#declared_staticも参照してください

于 2010-05-12T12:45:13.260 に答える
3

私の最初の反応は、オブジェクトでLoggerインスタンスをシリアル化することが理にかなっているのかどうか疑問に思うことです。後で逆シリアル化するとき、ロガーの環境が正しいことを期待するのは本当に公正ですか?私はむしろこれと一緒に行き、それを1日と呼びたいと思います:

private transient Logger logger = LoggerFactory.getLogger(this.getClass());
于 2010-05-12T13:00:18.250 に答える
0

ロガーをSerializableクラスに入れることはお勧めしません。

私の経験では、メモリが多すぎます。

また、このクラスをキャッシュしている場合、OutOfMemoryエラーが発生しやすくなります。

シリアル化可能なクラスのクリーニングを続けます。

ただし、ローカル環境または開発環境にいる場合。お気軽にどうぞ。

于 2021-10-14T11:23:07.357 に答える