16

コンパイラは、デバッグ目的 (ロギングなど) に使用されるステートメントを製品コードから削除できますか? デバッグ ステートメントは、おそらく注釈を使用して、何らかの方法でマークする必要があります。

プロパティを設定 (debug = true) し、デバッグ ステートメントごとに確認するのは簡単ですが、これによりパフォーマンスが低下する可能性があります。コンパイラが単純にデバッグ ステートメントを消去してくれるとよいでしょう。

4

8 に答える 8

24

おすすめは2つ。

最初 に: 実際のロギングには、log4j や Java 独自のビルトイン ロギングなどの最新のロギング パッケージを使用します。パフォーマンスについてはそれほど心配する必要はありません。ロギング レベルのチェックはナノ秒単位で行われます。(整数比較です)。

複数のログ ステートメントがある場合は、ブロック全体を保護します。

(log4j、例:)

if (logger.isDebugEnabled()) {

  // perform expensive operations
  // build string to log

  logger.debug("....");
}

これにより、実行時にロギングを制御する機能が追加されます。再起動してデバッグ ビルドを実行する必要があるのは、非常に不便です。

2番:

アサーションの方が必要なものであることがわかる場合があります。アサーションは、ブール値の結果に評価されるステートメントであり、オプションのメッセージがあります。

 assert (sky.state != FALLING) : "The sky is falling!";

アサーションの結果が false になるたびに、アサーションは失敗し、メッセージを含む AssertionError がスローされます (これは、アプリケーションを終了するための未チェックの例外です)。

すばらしいことに、これらは JVM によって特別に扱われ、実行時に VM パラメータを使用してクラス レベルに切り替えることができます (再コンパイルは不要です)。有効にしない場合、オーバーヘッドはゼロです。

于 2008-08-28T12:46:23.707 に答える
10
public abstract class Config
{
    public static final boolean ENABLELOGGING = true;
}

import static Config.*;

public class MyClass
{
    public myMethod()
    {
        System.out.println("Hello, non-logging world");

        if (ENABLELOGGING)
        {
            log("Hello, logging world.");
        }
    }
}

コンパイラは、"Hello, logging world." でコード ブロックを削除します。静的な最終値であるため、ENABLE_LOGGING が true に設定されている場合。proguard などの難読化ツールを使用すると、Config クラスも消失します。

難読化ツールは、代わりに次のようなことも許可します。

public class MyClass
{
    public myMethod()
    {
        System.out.println("Hello, non-logging world");

        Log.log("Hello, logging world.");
    }
}

import static Config.*;

public abstract class Log
{
    public static void log(String s)
    {
        if (ENABLELOGGING)
        {
            log(s);
        }
    }
}

メソッド Log#log は、コンパイラで何も残らず、難読化ツールによってそのメソッドへの呼び出しとともに削除され、最終的には Log クラス自体も削除されます。

于 2008-08-28T12:22:43.560 に答える
1

もう 1 つの可能性は、ロギング関数内に if ステートメントを配置することです。この方法ではコードが少なくなりますが、余分な関数呼び出しが発生します。

また、デバッグ コードを完全に削除することも好きではありません。本番環境では、問題が発生した場合にデバッグ メッセージにアクセスする必要があります。コード レベルのデバッグをすべて削除した場合、これは不可能です。

于 2008-08-28T14:52:49.020 に答える
0

Java には、独自のプリプロセッサが含まれています。それはAPTと呼ばれます。コードを処理して生成します。現時点では、これがどのように機能するかはわかりません(試したことはありません)。でも、こういうことに使われているようです。

于 2008-08-28T12:28:02.080 に答える
0

Java プリプロセッサを使用しますか? (google foo low ですが、これはそれについて議論している古い Joel フォーラムへのリンクです)

于 2008-08-28T11:46:19.123 に答える
0

また、ロギング フレームワークの使用を強くお勧めします。

これlogger.IsDebugEnabled()は必須ではありません。ログを記録する前に、システムがデバッグ レベルにあるかどうかを確認する方が高速であるというだけです。

ロギング フレームワークを使用すると、アプリケーションを再起動せずにその場でロギング レベルを設定できます。

次のようなログを記録できます。

logger.error("Something bad happened")
logger.debug("Something bad happend with loads more detail")
于 2008-08-28T14:11:10.977 に答える
-2

あなたの質問に直接答えるには:わかりません。

しかし、ここにあなたの問題に対する別の解決策があります。私の考えでは、ここで互いに衝突する 2 つのステートメントがあります。「デバッグ ステートメント」と「プロダクション コード」です。

デバッグ ステートメントの目的は何ですか? (単体) テスト中にバグを取り除くのに役立ちます。ソフトウェアの一部が適切にテストされ、要件に従って動作する場合、デバッグ ステートメントは時代遅れに他なりません。

プロダクション コードにデバッグ ステートメントを残すことには強く反対します。プロダクションコードでデバッグコードの副作用をテストすることを気にする人は誰もいないに違いありません。コードはおそらく本来の機能を果たしていますが、それ以上の機能を備えているのでしょうか? すべての #defines が正しく機能し、実際にすべてのデバッグ コードが取り除かれていますか? 100000 行の前処理されたコードを分析して、すべてのデバッグ要素がなくなったかどうかを確認するのは誰ですか?

プロダクション コードの定義が異なる場合を除き、コードのテスト後にデバッグ ステートメントを削除することを検討してください。

于 2008-08-28T12:35:08.350 に答える