2009-08-28 23 views
15

出力メッセージにコンパイル時定数として__LINE__を含める方法を探しています。Javaで__LINE__相当ですか?

__LINE__ in JSおよび__LINE__ in C#に示唆されているように、さまざまな解決策が存在するようですが、ランタイムペナルティが大きくなります。それらは通常、常にlog4jとして実行時オブジェクトStackFrameに基づいています。

log4jを必要に応じて有効/無効にすることは、通常はエラーが発生したとき、行番号を有効にするには遅すぎるため、インラインコードに行番号これ以上。 。理想的にEclipseのと統合何かで、

コンパイル前
  1. プリプロセスJavaソースファイルなので、それはまた者協会のプラットフォーム上でテストすることができます:それはどちらかすることが可能です。
  2. 前処理ローディング時のクラス。その場合、オーバーヘッドは償却されることによって無視できる。

1.実際に私は醜いハックを使用してください:

+0

私の好奇心のためだけに、ログに行番号が必要なのはなぜですか?エラーが発生すると、行番号を示す完全なスタックトレースが得られます。 – romaintaz

+3

時には、例外として、行番号の代わりに 'Util.java(Inlined Compiled Code)'のようなものがあります。そして、時には私は例外なく、ただ情報を記録するだけです: "ここにいる"、 "ここにいる"、私は一意のメッセージを持つことを嫌っていました(行番号はそれらをユニークにします) –

+0

JVMはその状況を処理する。どのJavaのバージョンを使用しますか? –

答えて

8

は、行情報は、クラスファイル内に存在するが、VMは、実行時にそれを捨てることができます。これは、Javaプログラムの起動時に指定できるオプションによって異なります。通常、デバッグ情報を使用して実行する場合のパフォーマンスの低下は、perm genのスペースの約5%にもう少しメモリを加えたものです。この情報は非常に貴重なものなので、私はこの情報を削除する理由は見当たりません。

あなたのコメント(Util.java(Inlined Compiled Code))は、あなたが積極的な最適化を使用していることを示唆しています。できれば、それらをオフにしてください。そのように、あなたは、単に行うことができます

// For Java 1.4, use new Exception().getStackTrace() 
int line = Thread.currentThread().getStackTrace()[0].getLineNumber(); 

あなたがそれを必要と

(すなわち内部 catchまたは if (log.isInfoEnabled())の)。

__LINE__の場合、Javaコンパイラはこれをサポートしていません。あなたの唯一の選択肢は、いくつかのハッキングを使ってソースをフィルタリングすることです。変数int __LINE__をどこかに定義し、それを必要に応じてランダムな値に設定することをお勧めします。 __LINE__ = \d+の番号を現在の行番号に置き換えるフィルタを作成します。これにより、行番号を固定することができます。

+0

'Thread.currentThread()。getStackTrace()'ではなく '新しいException()。getStackTrace()'が必要なのはなぜですか? –

+0

理由はありませんが、現在のスタックを取得する方法についてスレッドクラスを検索するのは面倒ではなかったことと、例外があることを知っていました:) –

+0

+1私の開発環境でも使用できる解決策( 'Thread .... 'を検索し、ビルドプロセスの行番号で置き換えてください) –

13

ANTトリックを経由してビルドサーバー上だけでチェックアウトした後、カスタムプリプロセッサを呼び出すことは、コンパイル時に起こるCで__LINE__の効果を得ることは不可能です時間。あなたはdebug=lineオプションでコンパイルする場合は、実行時にこのような関数を呼び出すことにより、行番号を取得することができます

public static int lineNumber() { 
    return Thread.currentThread().getStackTrace()[2].getLineNumber(); 
} 
+2

この情報にアクセスするには、回線に関するデバッグ情報をクラスファイルにコンパイルする必要があります。 – Mnementh

0

すぐに使えるJavaは、あなたが必要とするものを提供しているとは思わない。

しかし、独自の注釈プロセッサを作成し、Java 6.0 compiler APIsを使用する場合、この問題を解決できると思います。私はそれがどれほどの仕事になるかを推測することに気をつけません。

Eclipseでは、ビルドメカニズムに独自の注釈処理を含めることができます。

0

Javaコンパイラでは、このようなことについてはわかりません。しかし、ファイル内のlinenumberに__LINE__のようなトークンを置き換え、コンパイルする前にこのツールを実行するようにビルドプロセスを設定する、単純なプログラムを書くことができます。ある種のプリプロセッサ。

+0

それはまさに私が置き換えたいものです(脚注1参照)。 –

1

私はこのためにロギングフレームワークを使用し、それは面倒な詳細に対処しましょう。 java.util.loggingとlogbackはどちらも、LINEが提供できるものと同様の呼び出し元に関する情報を簡単に表示できます。

重要な利点は、情報が必要な場合にのみ計算されるため、出力がオーバーヘッドを必要としないことです。

5

これは、ボックス外にあることを実証します。これらのマクロは利用できません。 しかし、インスツルメンテーションとデバッグ情報を使用すると、インプリメンテーションできます。 check http://www.gallot.be/?p=85

4

このクラスでは、「ここに持ってきて、ここに来た」タイプのログを探していると、簡単に作業ができます。あなたが見たい場合は、

Log.v(TAG, Here.At()); 

をまたは:

public class Here { 
    public static String at() { 
     StackTraceElement ste = Thread.currentThread().getStackTrace()[3]; 
     String where = ste.getClassName() + " " + ste.getMethodName() + " " + ste.getLineNumber() + " "; 
     return where; 
    } 
} 

最も単純な形式でそれを使用する:私はちょうど次のクラス定義が含まれ、私は私のプロジェクトに追加したファイルHere.javaを持っています他のもの:

Log.v(TAG, Here.At() + String.format("interesting value = %d", my_val)); 

これは、最初の場合には「com.otherpackagenamestuff.MyClass MyMethodは225」を与える、と同じであるが、「面白い値= 123」が第2ケースに添付有するであろう。