2017-02-15 5 views
0

jvmは、ループ内でデカールされている場合、または繰り返しごとに新しいものを作成する場合、既存の参照を再利用しますか? 例:ループ内での参照の再利用

Date temporaryDate = null; 
    for (SomeObject o : collectionsOfObjects){ 
    temporaryDate = o.getDate(); 
    } 

for (SomeObject o : collectionsOfObjects){ 
    Date temporaryDate = o.getDate(); 
} 

ただ、我々はDate型の新しい参照を作成したり、多分、JVMごとにループが下にそれを最適化するため、最初の例では、より多くのメモリ消費量になりますかしらことを確認すると、反復ごとに同じ参照を使用します。

+0

リファレンスはどのように再利用できますか? – Andremoniy

+0

最初のものとは別のオブジェクトを指すことができます – marm

+3

「参照」という言葉を誤って使用していると思います。 "変数' temporaryDate'は、各繰り返しで同じ記憶場所を使用していますか? (参照は変数の* value *であり、繰り返し処理されるオブジェクトに依存します) –

答えて

0

ローカル変数のスコープは、コンパイル時のアーティファクトです。コンパイラ(例えば、javac)がソースコードからバイトコードを生成するとき、この情報は既に失われています。

Javaバイトコードは、ローカル変数に相当するstack frame内の格納場所を位置番号で参照します。これらの位置へのローカル変数の割り当てと、スタックフレームに必要な最大ストレージの計算は、コンパイル時に行われます。

コンパイラは、分離したスコープを持つ変数に対してスタックフレーム内のストレージを再利用することができますが、必須ではありません(通常はそうします)。しかし、あなたの例では、分離したスコープを持つ変数はありません。ループの本体内には、同時に3つの変数が存在します(temporaryDateo)。名前のない変数はIteratorです。これらの変数がすべて同時に存在する点があるので、それらは異なる格納位置を持たなければならず、スタックフレームは少なくとも3のサイズでなければなりません。これは両方のバリエーションに適用されるため、関連する相違はありません。

しかし、スタックフレーム内のストレージは、分離したスコープを持つ変数に対してのみ再利用できるため、変数のスコープを制限してください(とにかく良い方法です)。あなたは

for(SomeObject o : collectionsOfObjects){ 
    Date temporaryDate = o.getDate(); 
} 
for(OtherObject other : collectionsOfObjects){ 
    String n = other.getName(); 
} 

を書くときに最初のループのために必要なすべての3つの変数のストレージは、第二のループ(異なるタイプの問題ではありません)で再利用することができます。 temporaryDateがループ外で宣言された場合、2番目のループでその記憶域を再利用することは不可能です。

スタックフレームはメソッドエントリに割り当てられ、とにかくメソッド終了時に破棄されることに注意してください。ローカル変数の宣言は割り当てやアクションをまったく引き起こしません。実行時には、実際の読み書きだけが重要です。したがって、変数を宣言する方法はパフォーマンスに影響しません。

JVMが(HotSpot/OpenJDKのような洗練されたJVMについて)コードの最適化を開始すると、コードがStatic single assignment formに変換されます。これは宣言とはまったく異なって見える可能性があります。この形式では、未使用の変数を完全に削除したり、同じ値を予測可能に保持したり、冗長な計算を排除したり、予測結果で置換するなどの基本的な最適化が可能です。

関連する問題