'sock'という名前のソケット変数があり、何らかの理由で新しいソケットを作成する必要がある場合は、'sock2'と呼ばれ、'sock2'を'sock'と等しくなるように設定します。次に、変数「sock」を破棄します。接続は引き続き機能しますか?「sock2」は、元々「sock」にあったソケットのもう一方の端と通信できますか?
2 に答える
sock
元々 (の形式で)あったオブジェクトへの参照がまだあるためsock2
、Javaガベージコレクションはそれを破棄せず、sock2
あたかもそうであるかのように使用できますsock
。
基本的にあなたはこのようなことを説明しています
public void test (...) {
Socket sock2;
{
Socket sock = // open socket
sock2 = sock;
// now 'sock' does out of scope; i.e. you "throw it away"
}
// use 'sock2'
}
はい、問題なく動作します。sock
とは両方ともsock2
参照変数です(プリミティブ型ではないJavaのすべての変数も同様です!)。割り当てsock2 = sock;
は参照を割り当てるだけです...これで同じものをsock2
指すようになり、それを使用して、を介して最初に通信していたリモートホストと通信できます。Socket
sock
sock
さて、以前にsが異なるsock2
ことを指摘した場合はどうでしょうか。 Socket
public void test (...) {
Socket sock2 = // open socket to A
{
Socket sock = // open socket to B
sock2 = sock;
// now 'sock' does out of scope; i.e. you "throw it away"
}
// use 'sock2'
}
以前と同様に、引き続き機能します。同じ理由で。
これをキャッチするのは、Aに接続されたソケットへの参照を削除したことだけです。ソケットへの参照がなくなった場合A
、アプリケーションはそれを使用できません。(これはあなたが話す能力に影響を与えませんB
...'あなたはまだその参照を持っています...でsock2
)。
では、今何が起こっているのでしょうか?さて、JavaSocket
オブジェクトforA
がコードで使用できなくなったという状況が発生しました。(Javaの用語では、オブジェクトは「到達不能」です。)これは、ガベージコレクションの対象となることを意味します。ただし、すぐにガベージコレクションされるという意味ではありません。実際、ガベージコレクターが実行されるまでに数秒...または数日...かかる可能性があります。それまでの間、ローカルおよびリモートでリソースを拘束している一部のリモートホストへの接続が開いている可能性があります。これはリソースリークであり、深刻な結果をもたらす可能性があります。(GCが最終的にソケットを再利用すると、実装オブジェクトのファイナライザーは基盤となる接続を閉じ、リソースを解放します。ただし、損傷はすでに発生している可能性があります。)
close()
解決策は、コードがタイムリーに作成するオブジェクトを常に確認しSocket
、参照が単に「床に落ちる」ことを許可しないようにすることです。