3

Javaは値によって渡されることを読みました。HashMap somehashMapしたがって、このコードがあり、がよりも寿命が長いとしましょうfoo。したがって、fooをマップ内に配置し、そこから削除するのを忘れたという理由だけでfooが機能したとしても、fooをガベージコレクションすることは許可されていません。リンクした投稿の回答のロジックをたどると、実際にはの参照のコピーがfooメソッドのput()権利に渡されますか?その場合、に入れるfooことHashMapでガベージコレクションを防ぐことはできません。ここで何が起こっているのか理解するのを手伝ってくれませんか?私は正確に何が欠けていますか?

 public void someMethod(){
     Foo foo  = new Foo();
     somehashMap.put(fooKey,foo); 
  }
4

9 に答える 9

11

ガベージコレクションは参照には適用できませんが、ヒープに存在する実際のオブジェクトには適用できません。を挿入すると、基本的fooMap、現在のスコープから「脱出」し、と同じスコープ/ライフタイムに配置するのに役立ちますsomehashMap

Javaでの参照は、バックグラウンドで透過的に処理されます。foo参照をマップに配置すると、参照putのコピーが実際にメソッド呼び出しに渡されますが、基になるオブジェクトnew Foo()は、元の参照とコピーされた参照の両方で同じです。以下のスニペットを見てみましょう。

public void doIt() {
  Object f1 = new Object();
  Object f2 = f1;
  Object f3 = f2;
}

doIt上記のスニペットでは、完了の実行後にガベージコレクションされるオブジェクトはいくつですか?new Object()それは私たちが作成したシングルです。残りはすべて、同じオブジェクトを指すために使用される単なる参照またはエイリアスです。

于 2012-07-31T13:26:37.577 に答える
7

オブジェクトが到達可能である限り、オブジェクトをガベージコレクションすることはできません。あなたの場合、fooに到達できるFoo foo = someHashMap.get(fooKey);ので、マップ内にあり、マップ自体に到達可能である限り、ガベージコレクションを行うことはできません。

于 2012-07-31T13:27:26.327 に答える
6

参照が実際に何であるかについて、あなたは明確ではないと思います。

'foo'がオブジェクトへの参照であり、それをハッシュマップに追加すると、同じオブジェクトへの2番目の参照が効果的に作成されることは部分的に正しいです。

ただし、これがまさに、「foo」変数が消えたときにオブジェクトがガベージコレクションされない理由です。オブジェクトは、参照が残っていない場合にのみガベージコレクションされます。1つの参照(foo)から始めて、2番目の参照(ハッシュマップ内)を作成します。最初の参照は関数が終了すると消えますが、まだ1つの参照が残っています。

于 2012-07-31T13:28:18.263 に答える
6

写真を試してみてください:

ここに画像の説明を入力してください

ボックスはオブジェクトです。ボックス化されていない文字は変数です。

最初は、関数が呼び出される前に存在すると想定しているハッシュマップがあり、その後も存在し続けます。

次にnew Foo()、新しいオブジェクトをf=作成し、それを参照する変数を作成します。

次にhashmap.put(k,f)、fと同じオブジェクトを指すエントリをハッシュマップに作成します。

次に、関数を終了すると、ローカル変数fは存在しなくなりますが、それ以外はすべて残ります。

ガベージコレクターは、ハッシュマップがまだFooオブジェクトを指しているため、Fooオブジェクトを削除しません。そして、それはあなたが望むものです-後で呼び出す場合hashmap.get(k)は、そのFooオブジェクトを取得することを期待します。

ハッシュマップからエントリを削除するとhashmap.remove(k)、Fooオブジェクトをガベージコレクションできます。

ハッシュマップ自体が存在しなくなった場合、Fooオブジェクトをガベージコレクションできます。

于 2012-07-31T13:51:44.210 に答える
3

ガベージコレクターを備えたほとんどの言語は、ある種の弱参照をサポートしています。たとえば、Javaで弱いハッシュマップの実装を見つけることができます。fooオブジェクトをウィークハッシュマップに配置し、ガベージコレクターが実行される場合、fooへの他のポインター(週ポインターを除く)が存在しない場合、fooオブジェクトが収集され、ウィークハッシュマップから削除されます。この方法でメモリリークを回避できる場合があります。

于 2012-07-31T13:27:18.413 に答える
2

fooがHashMapにある限り、ガベージコレクションはできません。Javaは、fooが二度と使用されないことを認識していないためです。fooは、すべての参照が終了するとすぐにガベージコレクションされる可能性があります。

于 2012-07-31T13:28:02.893 に答える
2

実際には、fooの参照のコピーをput()メソッドに渡していますか?

はい、Javaはインターンマップが保持referenceしている参照のコピーをsame objectメモリ(heap)に渡しているため、マップが作成されるまでGCの対象にはなりません。

于 2012-07-31T13:28:20.413 に答える
1

このputメソッドの場合の値渡しは、への参照の値ですfoo。参照がカウントされるため、参照を保持しているfoo限り、ガベージコレクションは行われません。somehashMapfoo

誰かがマップを使用して画像をキャッシュしている場所で継承したコードで、このようなメモリリークが見つかりましたが、画像が再度必要になったときに、キャッシュされた画像を取得する代わりに、新しい画像が作成され、マップにプッシュされました。新しいキー。

于 2012-07-31T13:27:34.503 に答える
1

Javaは確かに値を渡します。ただし、オブジェクトのインスタンスではなく、値で参照を渡します。

于 2012-07-31T13:28:25.173 に答える