質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Q&A

5回答

2102閲覧

参照の連鎖

snow_wind

総合スコア9

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

0グッド

1クリップ

投稿2015/11/24 10:46

ガベレージコレクションについて勉強していて、よく分からなくなりました。
あるインスタンスが生存し続けるためにはある変数がそのインスタンスへの参照を保持していなければならない。局所変数はスコープ外に出れば消えてしまう。インスタンス変数が参照している場合は、そのインスタンスへの参照を保持している変数がなくなればやっぱり道連れに消えてしまう。するとあるインスタンスが確実に生存し続けるためには参照の連鎖の始点に静的変数による参照が必要、ということになるでしょうか?

また、静的変数が所属しているインスタンス(Classクラスでしょうか・・)があると思いますが、そのインスタンスはまた別の変数に参照されているのでしょうか。それともこのインスタンスは何にも参照されずとも残り続ける特殊なインスタンスなのでしょうか。

断片を繋ぎ合せた勝手な理解なので根本的な間違いがありそうですが、その指摘も含めてご回答よろしくお願いします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答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

raccy

総合スコア21735

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

あるインスタンスが確実に生存し続けるためには参照の連鎖の始点に静的変数による参照が必要

「違います」といった方が正解に近いと思います。

インスタンスが「確実に生存し続ける」必要がある期間は「使う可能性がある(いいかえればプログラムから参照される可能性がある)」間です。動いているプログラムが必要とする情報がどこにあるかというと本質的にはそれはスタックにあります。静的フィールド(実装上はクラスオブジェクト)にではありません。

そんなわけでGarbage Collectorは任意のインスタンスが「使われなくなったかどうか」の判断のために、実行スタック(ローカル変数やメソッドの引数を覚えておく領域)から参照される可能性があるインスタンスを調べ上げます。クラスの静的フィールドに参照があったとしてもそれを基点として特別扱いはしません。なぜならクラス自体も、どこからも参照されなくなれば回収可能だからです。(もっともそういうクラスの利用はかなり特殊なプログラムになりますが)

静的フィールドに覚えておくと普通はプログラム終了時点までインスタンスは生存し続けますが、それは静的フィールドが存在しているクラスオブジェクトの参照が実行スタックからたどれるからに過ぎません。実行スタックにはローカル変数やメソッドの引数はもちろんですが、実行中のメソッドがなにかも記録されています。スタックにあるメソッドMが存在しているとメソッドM実行中はそのメソッドが定義されているクラスオブジェクトも存在し続ける必要があります。さらにそのクラス(のフィールドやメソッド)が直接・間接に参照している別のクラスも同様に存在し続けなければなりません。そういう関係もGarbage Collectorはたどっていきます。そんなわけで静的フィールドに覚えておくとたいていはプログラム終了時までずっと消えなくなるのです。

補記:raccyさんの回答にある「発想が逆」という言葉。まさにそう思いました。プログラマーがGarbage Collectorがどう動くか考えて設計するのではなく、逆に自然に記述されたプログラムが適切に動作するようにGarbage Collectorの方がよろしくやってくれると考えるべきだと思いマス。

投稿2015/11/24 14:21

編集2015/11/24 14:37
KSOH

総合スコア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

akiruno-oneone

総合スコア815

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

関数(メソッド)の戻り値として返す方法があります。

勉強されている言語を教えて頂ければ、具体的な例を挙げて説明することもできるかと思います。

投稿2015/11/24 10:53

編集2015/11/24 10:56
yuni-net

総合スコア10

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

snow_wind

2015/11/24 11:11

基本情報の不足、申し訳ありません。 Javaを勉強しております。よろしくお願いします。
guest

0

スコープを理解すると良いでしょう。

投稿2015/11/24 10:52

Orlofsky

総合スコア16415

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問