2012-06-06 9 views
13

アサーションは、それぞれ実行時にデバッグとプロダクション用に有効/無効を切り替えることができます。しかし私は、アサーションが生成されたバイナリのサイズを増やすことも発見しました(下の例では約100-200バイト)。アサーションなしのコンパイル

CおよびC++では、#define NDEBUGの前に#include <assert.h>のようにコンパイルすることができます。

Javaコンパイラがこれを自動的に行う方法はありますか?私は後でデバッグの目的でソースコードにそれらを残したいと思います。しかし、結果のバイナリを必要以上に大きくすることは望ましくありません(設計要件としてサイズ制限があります)。

Cコード:

//#define NDEBUG 
#include <assert.h> 

int main(void) { 
    assert(0); // +200 bytes without NDEBUG, 0 with NDEBUG 
    return 0; 
} 

Javaコード:bnをすることに応答して

public class Test { 
    public static void main(String[] args) { 
     assert(System.nanoTime()==0); // increases binary size by about 200 bytes 
    } 
} 

の答え:

public class Test2 { 
    public static final boolean assertions = false; 

    public static void main(String[] args) { 
     if(assertions) { 
      assert(System.nanoTime()==0); 
     } 
    } 
} 

EDIT:実際には、それはそうこの機能の有効化/無効化は、より便利なコンパイル時間ですe機能を提供します。つまり、何人のエンドユーザーがそれらを有効にするのでしょうか?デバッグプロセス中にプログラマが関心を持つ限り、彼はおそらくコードを再コンパイルします。

+0

これは、すべてのアサーションのコストが200バイトであることを証明するものではありません。 – EJP

+1

@EJP:確かに。私が意味していたのは、全体としてアサーションによって引き起こされた無視できない増加があったということでした。正確な金額は確かに声明の複雑さに左右されます。 – tskuzzy

+1

このようなことを気にするなら、あなたは間違った言葉を使います。 – lvella

答えて

2

個人Iが原因で複雑で次のことをしないだろうが、ソースコードに追加しかしjavacは、次の二つの断片にmainの正確な同じ中間コードを生成した:

条件は

class C { 
    public final static boolean assertions = false; 

    public static void main(String[] args) { 
     if(assertions) { 
      assert(System.nanoTime()==0); 
     } 
    } 
} 
をアサート

はありません

class C { 
    public static void main(String[] args) { 
    } 
} 
をアサート

コンパイルされたコード

public static void main(java.lang.String[]); 
    Code: 
     0: return   
    LineNumberTable: 
     line 3: 0 

EDIT実際に

は、この有効/無効は、実行時よりも有用 コンパイル時の機能であるように私には思えます。つまり、どれくらい多くのエンドユーザーが を有効にするのでしょうか?

有効にするエンドユーザーではなく、エンドユーザーが有効にすることをエンドユーザーに指示します。私は彼らがデフォルトで無効にされているのではなく、有効にされていることを望みます。

+0

完璧なおかげで!私はそれが非常にエレガントな解決ではないことに同意するが、私の質問に対処します。 – tskuzzy

+0

'public final static boolean assertions = false;'という変数を分離したクラスに置いて、あなたのコード全体にアサートを使い、フラグをある場所で変更できるようにするには、全体を再コンパイルする必要がありますあなたがコンパイルされたコードから変数を消去したいので、それが変更されている場合はsourceを使用してください。 – lvella

+0

@Ivellaこれは、コンパイラがpublic static finalをインライン化するためです。 –

4

これは組み込みのステップとしては不可能です。ただし、アサーションの周りに条件ブロックを追加することでこれを行うことができます。

詳細については、記事"Removing all Trace of Assertions from Class Files"を参照してください。

+0

実際には良いアイデアだと思いますが、バイナリをさらに50バイト増やしました。 – tskuzzy

+0

コンパイラはステートメントを完全に削除する必要があります。なぜなら、今は到達できないためです。 – Robin

+2

@Robin OPが「final」を使用するとサイズが小さくなります。 –

関連する問題