ガベレージコレクションについて勉強していて、よく分からなくなりました。
あるインスタンスが生存し続けるためにはある変数がそのインスタンスへの参照を保持していなければならない。局所変数はスコープ外に出れば消えてしまう。インスタンス変数が参照している場合は、そのインスタンスへの参照を保持している変数がなくなればやっぱり道連れに消えてしまう。するとあるインスタンスが確実に生存し続けるためには参照の連鎖の始点に静的変数による参照が必要、ということになるでしょうか?
また、静的変数が所属しているインスタンス(Classクラスでしょうか・・)があると思いますが、そのインスタンスはまた別の変数に参照されているのでしょうか。それともこのインスタンスは何にも参照されずとも残り続ける特殊なインスタンスなのでしょうか。
断片を繋ぎ合せた勝手な理解なので根本的な間違いがありそうですが、その指摘も含めてご回答よろしくお願いします。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答5件
0
発想が逆です。
ガベージコレクション(以下、GC)は、なにかしらの経路で到達できるオブジェクトを除いたオブジェクト※1をなるべく回収(削除)していこうとする仕組みです。いつ回収するかはわかりませんし、GCが動作した時に必ず回収するとも限りません※2。到達できるというのは現在利用可能なオブジェクトから参照していったら直接または間接的にいつかは辿り着けるということです※3。つまり、現在利用しているか、これから利用できるオブジェクトの事です。逆に到達できないオブジェクトはどのように参照を辿っても決してアクセスできない、つまり、利用できないオブジェクトです。プログラム内で、今後利用することは原理的に不可能なので、回収してもしなくてもプログラムの動作には一切影響を与えません。
オブジェクトを回収されないようにどうすればいいのか?ですが、逆に言うと、オブジェクトへの参照(どう辿り着くのか)をどう確保するのか?になります。例えば、あるメソッドのローカル変数x
に入っているオブジェクトXを、そのメソッドが終了後も参照する、つまりアクセスするにはどうしたらいいのか?を考えるのです。ローカル変数はメソッドが終了した後は使えません。なので、メソッドが終了後もアクセス可能な変数(静的変数でもメンバー変数でも何でもいいです)にオブジェクトXを代入する(○○ = x;
)か、メソッド自体の戻り値としてオブジェクトXを返す(return x;
)とすれば、メソッド終了後もx
に入っていたオブジェクトXへアクセスでき(到達でき)ます。そうすると、メソッド終了後もオブジェクトXが回収されることはありません。※4
なお、クラスの静的変数は、プログラムのどこでも利用可能ですし、プログラムの開始から終了まで利用可能なものです。つまり、常に到達できるオブジェクトなので、回収されることはありません。
※1 例外的に、__弱参照__という特別なオブジェクトは、到達可能であっても回収の対象になる場合があります。
※2 Javaを含む各言語の最新バージョンでは__世代別GC__というものを採用しており、オブジェクトの大きさ等によって回収のタイミングが変わる場合があります。
※3 ここでの辿り着けるはpublicやprivate等と言ったアクセス権は無視されます。内部的に辿り着けるかどうかだけが問題になります。
※4 逆にそういったことをしなかった場合、すぐにGCに回収されると言うわけではありません。あくまでGCにそのうち回収されるようになるだけで、いつ回収されるかはわかりません。ただ、たとえ回収されずに生きたままであっても、アクセス方法がないため、そのオブジェクトを利用することは不可能です。
※ 上の話はJava等のGCがある一般的な言語の話ですが、言語やバージョンによっては仕組みが多少異なる場合があります。
投稿2015/11/24 12:29
総合スコア21735
0
あるインスタンスが確実に生存し続けるためには参照の連鎖の始点に静的変数による参照が必要
「違います」といった方が正解に近いと思います。
インスタンスが「確実に生存し続ける」必要がある期間は「使う可能性がある(いいかえればプログラムから参照される可能性がある)」間です。動いているプログラムが必要とする情報がどこにあるかというと本質的にはそれはスタックにあります。静的フィールド(実装上はクラスオブジェクト)にではありません。
そんなわけでGarbage Collectorは任意のインスタンスが「使われなくなったかどうか」の判断のために、実行スタック(ローカル変数やメソッドの引数を覚えておく領域)から参照される可能性があるインスタンスを調べ上げます。クラスの静的フィールドに参照があったとしてもそれを基点として特別扱いはしません。なぜならクラス自体も、どこからも参照されなくなれば回収可能だからです。(もっともそういうクラスの利用はかなり特殊なプログラムになりますが)
静的フィールドに覚えておくと普通はプログラム終了時点までインスタンスは生存し続けますが、それは静的フィールドが存在しているクラスオブジェクトの参照が実行スタックからたどれるからに過ぎません。実行スタックにはローカル変数やメソッドの引数はもちろんですが、実行中のメソッドがなにかも記録されています。スタックにあるメソッドMが存在しているとメソッドM実行中はそのメソッドが定義されているクラスオブジェクトも存在し続ける必要があります。さらにそのクラス(のフィールドやメソッド)が直接・間接に参照している別のクラスも同様に存在し続けなければなりません。そういう関係もGarbage Collectorはたどっていきます。そんなわけで静的フィールドに覚えておくとたいていはプログラム終了時までずっと消えなくなるのです。
補記:raccyさんの回答にある「発想が逆」という言葉。まさにそう思いました。プログラマーがGarbage Collectorがどう動くか考えて設計するのではなく、逆に自然に記述されたプログラムが適切に動作するようにGarbage Collectorの方がよろしくやってくれると考えるべきだと思いマス。
投稿2015/11/24 14:21
編集2015/11/24 14:37総合スコア12
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
あるインスタンスが生存し続けるためにはある変数がそのインスタンスへの参照を保持していなければならない。局所変数はスコープ外に出れば消えてしまう。
インスタンス変数が参照している場合は、そのインスタンスへの参照を保持している変数がなくなればやっぱり道連れに消えてしまう。
その通りだと考えます。
参照している変数がなくなれば、それらのインスタンスはガベージコレクションの対象となります。
するとあるインスタンスが確実に生存し続けるためには参照の連鎖の始点に静的変数による参照が必要、ということになるでしょうか?
「連鎖」になる必要はないですが、インスタンスが確実に存在し続けるには、静的変数による参照が必要です。
静的変数による例として、シングルトンパターンと呼ばれるものがあります。
これは、インスタンスを1つしか持たない(持たせない)クラスを作成するときに使います。
「シングルトン」でググれば以下のようなコードがでてくると思います。
java
1public class Hoge { 2 /* 唯一のインスタンス。 スタティック変数にする。 */ 3 private static final Hoge instance = new Hoge(); 4 /** 5 * コンストラクタ。 6 * プライベートにして、他からnewできなようにする。 7 */ 8 private Hoge() { 9 } 10 /** 11 * このクラスの唯一のインスタンスを返す。 12 */ 13 public static Hoge getInstance() { 14 return instance; 15 } 16}
静的変数がなくなる(?)のは、プログラムが終了するときですので、このインスタンスがなくなることはありません。
投稿2015/11/24 14:54
総合スコア815
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
関数(メソッド)の戻り値として返す方法があります。
勉強されている言語を教えて頂ければ、具体的な例を挙げて説明することもできるかと思います。
投稿2015/11/24 10:53
編集2015/11/24 10:56総合スコア10
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。