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

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

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

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

Q&A

解決済

4回答

883閲覧

Java インスタンスについて

退会済みユーザー

退会済みユーザー

総合スコア0

Java

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

0グッド

2クリップ

投稿2020/02/06 14:09

Javaのインスタンスについて
参照型変数に代入される値は、メモリ上に作られたインスタンスへの参照ですが

Java

1Object o = new Object(); 2o = null;

このようなコードがあるとき変数oにnullが入ることにより、
変数oが参照していたインスタンスはどの変数からも参照されていない状態になります。
このインスタンスはGCの対象になると思うのですが、すぐに消されるわけでわないと思います。
もしこのインスタンスを利用したくなったとき
、再度このインスタンスをプログラム側で利用できる方法はあるのでしょうか?

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

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

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

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

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

Zuishin

2020/02/06 14:47

全くどこからも参照されていないなら無理ですが、クロージャでキャプチャされていたりイベントを捕まえていたりすれば可能性があります。具体的にどう利用しようとしていますか?
退会済みユーザー

退会済みユーザー

2020/02/06 15:09

具体的にどこで利用しようと考えて質問したわけではなく、GCの勉強中にふと再利用できるのか気になり質問させていただきました。 何なら自分自身が「こんなの質問しても役に立たないだろうなw」と思いつつ興味本位で質問しました。質問返しになってしまい申し訳ないですが、もし利用する機会があるのなら教えていただきたいです。m(__)m
Zuishin

2020/02/07 11:09

回答に書いたように、ファイナライザで Java 由来でない、たとえば OS 由来のリソースを解放するのが唯一と言っていい利用法ではないかと思います。 弱参照は WeakReference などの、ガベージコレクションに影響を与えない三種類の参照のことですが、ガベージコレクションに影響を与えないとは言え、これは参照です。なので、「弱参照が無い場合」と但し書きを入れています。 弱参照経由でオブジェクトを変更することは許されません。この参照はガベージコレクションに影響しないので、いつ消えるかわからないからです。 回答の意味がわかったかわからないか、わからないならどこがわからないのかを書いてください。
退会済みユーザー

退会済みユーザー

2020/02/09 02:59

私の知識不足で理解できないことが多かったので、自分で勉強して理解を深めようと思います。回答者の皆さんに追いつけるよう頑張ろうと思います。ありがとうございました!
Zuishin

2020/02/09 03:00

どこがわからないかを書いてください。
退会済みユーザー

退会済みユーザー

2020/02/09 03:08

Object o = nullとしてしまえば ファイナライザをプログラマが明示的に呼ぶのは不可なのでは?と思いました。
Zuishin

2020/02/09 03:10

タイミングを指定できなければならないとは質問のどこにもありません。
退会済みユーザー

退会済みユーザー

2020/02/09 03:20

私は質問に「もしこのインスタンスを利用したくなったとき」と書きました。 なので、この質問を見た人は「どこからも参照されていない状態でプログラマが利用できるのかを聞きたいんだな」と理解してくださってくれると勝手に思っていました。たしかに回答者様のようにGCのファイナライザによる利用もこの質問に対する回答として合っています。これは見た人によって捉え方が変わってしまう質問の仕方をした私のミスです。今後は気をつけます。 申し訳ありません。m(__)m
Zuishin

2020/02/09 03:22

それについては既に書きました。 > 全くどこからも参照されていないなら無理ですが、クロージャでキャプチャされていたりイベントを捕まえていたりすれば可能性があります。 「無理です」とはっきり書いています。それを踏まえてさらに踏み込んで聞きたいという要請に応えたものです。
Zuishin

2020/02/09 03:24

つまり、あなたの質問に答えた上で質問の意図を尋ね、それに応えたものですが、それを「理解できませんでした」と放置するのはどういう了見ですか?
退会済みユーザー

退会済みユーザー

2020/02/09 03:26

クロージャやイベント(これはマウスクリックのインタフェースなどでしょうか?) にキャッチされているというものが理解できませんでした。 ただ、これ以上は聞くと回答者様の負担になってしまうと思ったので、自分で理解しようと思ったのです。
Zuishin

2020/02/09 03:31

参照が無い物は自由に使えないというのは当然のことであって、それを無理やり使おうとすること自体が間違っています。普通にできるはずはありません。 しかしファイナライザでなら使えるしメリットもあり、使うコードも実際の現場で使われています。 利用法は示した通りで、あなたの想像とは違うものであったというだけのことです。 あなたの思う通りの利用法はできません。それは「無理」とはっきりと書いています。「無理」の二字が理解できませんでしたか?
退会済みユーザー

退会済みユーザー

2020/02/09 03:35

「参照が無い物は自由に使えないというのは当然のことであって」これはあなたにとっては当然かもしれませんが私はできるかな?と好奇心で質問したのです。これ以上は回答を参考に自分で勉強するのでこれで終わらせてください。
Zuishin

2020/02/09 03:42

それに対しては「無理」と書きました。この二文字の意味がわからなかったので放置したということですか?
退会済みユーザー

退会済みユーザー

2020/02/09 03:44

放置というのはどういうことですか?
退会済みユーザー

退会済みユーザー

2020/02/09 03:45

私は放置したつもりはありません。
Zuishin

2020/02/09 03:45

私は自分から回答したのではありません。あなたに聞かれたから回答したのに放置した理由を尋ねています。嫌がらせであるなら次回からはやめていただきたい。広告の裏などを使ってください。
退会済みユーザー

退会済みユーザー

2020/02/09 03:46

だからなぜ放置したと捉えたのですか?
Zuishin

2020/02/09 03:47

放置というのは、自分から聞いたにも関わらず何の反応もせず、どこがわからないか聞くように再三言ったにも関わらず無視して「理解できないから終了」したことを指しています。次からはどうぞ人に迷惑のかからないところでしてください。
退会済みユーザー

退会済みユーザー

2020/02/09 03:49

私は返信に1日から2日しか開けていませんよ?
Zuishin

2020/02/09 03:51

無視して終了したじゃないですか。
Zuishin

2020/02/09 03:52

今回の件に関してはいいので、次回からは広告の裏でどうぞ、と言っています。まだ何か?
退会済みユーザー

退会済みユーザー

2020/02/09 03:53

終了というのはベストアンサーを決めたのが終了ということですか?
Zuishin

2020/02/09 03:54

そこから?
guest

回答4

0

メモリが解放される前にファイナライザが呼ばれます。このファイナライザはなるべく使わないようにします。しかし、例外もあります。

MET12-J. ファイナライザは使わない

ネイティブコードを使ったプログラムを作成する場合にはファイナライザを使用してもよい。その理由は、他の言語で書かれたコードによって使用されるメモリをガベージコレクションすることは出来ないからであり、オブジェクトの生存期間も分からないからである。

ファイナライザが走る時にはそのオブジェクトは、弱参照がある場合を除いてどこからも参照されていないはずなので、弱参照が無い場合には「どこからも参照されていないインスタンスの利用」にあたると思います。

投稿2020/02/06 15:27

編集2020/02/06 23:31
Zuishin

総合スコア28660

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

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

0

ベストアンサー

どこからも参照しなくなったインスタンスを再利用することはできません。

インスタンス生成時にクラス側にキャッシュしておいて、インスタンスを再利用することはできます。
例えば、Integerの -128~127 はキャッシュされていて、インスタンスを共有・再利用してます。
シングルトンパターンでは、インスタンスを1つだけ作って共有・再利用します。

投稿2020/02/06 14:44

編集2020/02/06 14:45
shiracamus

総合スコア5406

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

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

退会済みユーザー

退会済みユーザー

2020/02/06 15:14

回答ありがとうございますm(__)m やはり完全にどこからも参照されていない状態では、GCに殺されるしかない運命なのですね...
Zuishin

2020/02/09 03:08

私の回答のどこがわからなかったか聞いてくださいと言いました。あなたの要請によって回答したものですが、それを理解できなかったで済ませるのはいかがなものかと思います。
swordone

2020/02/09 03:25

atsushiさん そもそもの発想が違う気がします。 必要なくなって消したいけど、それをその都度いちいち消すと負荷が大きくなったり本来のやりたい動作が遅くなったりするので、コンピュータにとって良きときにまとめてGCで消そうとしているだけであって、そんなものへの参照を取得しようということ自体想定していないはずです。
退会済みユーザー

退会済みユーザー

2020/02/09 03:58

たしかにそれが当たり前なのですが そういうことはできるかな?と興味本位で質問しました。 ありがとうございますm(__)m
guest

0

ファイナライザでthisを別の所に参照させた場合、何処にも参照されていなかった状態でも、GC回収のタイミングで参照が作られせて、再利用できるようにすることはできるようです。(ただし、finalize()はJava 9からdeprecatedですので、使用しない方が良いです。)

Java

1public class prog { 2 public static Hoge hoge; 3 4 public static void main(String[] args) throws Exception { 5 f(); 6 System.out.println("--"); 7 if (hoge != null) { 8 System.out.println(hoge.n); 9 } 10 System.gc(); 11 System.out.println("--"); 12 if (hoge != null) { 13 System.out.println(hoge.n); 14 } 15 System.gc(); 16 System.out.println("--"); 17 if (hoge != null) { 18 System.out.println(hoge.n); 19 } 20 System.gc(); 21 System.out.println("--"); 22 if (hoge != null) { 23 System.out.println(hoge.n); 24 } 25 System.gc(); 26 System.out.println("--"); 27 if (hoge != null) { 28 System.out.println(hoge.n); 29 } 30 System.gc(); 31 System.out.println("--"); 32 if (hoge != null) { 33 System.out.println(hoge.n); 34 } 35 } 36 public static void f() { 37 Hoge hoge = new Hoge(42); 38 System.out.println(hoge.n); 39 } 40 41 public static class Hoge { 42 public int n; 43 public Hoge(int n) { 44 this.n = n; 45 } 46 public void finalize() { 47 System.out.println("finalize!"); 48 this.n++; 49 prog.hoge = this; 50 } 51 } 52}

Wandboxで実行

ただ、GCが走るまでは本当に参照がないので、利用はできません。なお、この後hogeをnullにしても、二回目のファイナライザは動かなかったので、このオブジェクトがGC処理の前に戻ったと言うことでもないようです。GCからみてどういう状態になっているのかはわかりませんでした。(詳しい人、教えてください。)


【おまけ】

Ruby等他言語では、Objectのidを取得して、そこからオブジェクトを取り出すというのはできます。

Ruby

1def hoge 2 a = String.new 3 a << "abc" 4 a.__id__ 5end 6 7id = hoge 8p GC.count 9p ObjectSpace._id2ref(id) 10p GC.count 11GC.start 12p GC.count 13p ObjectSpace._id2ref(id) 14p GC.count 15GC.start 16p GC.count 17p ObjectSpace._id2ref(id)

上のRubyの例ではGCで回収された後にアクセスしようとするとエラーになりますが、回収前ならアクセス可能です。

Javaで同等の機能を見つけようとしたのですが、普通のAPIにはないようです。"java.bsae/jdk.internal"(内部用のAPI、通常は隠しになっていて、ドキュメントもない)にあるものも一通り見てみましたが、なさそうでした。もしどうしてもしたいなら、C等でnative実装するしかないと思います。(オブジェクトのID取得に使われるSystem#identityHashCode(Object)も直接native実装で、内部APIを使っているわけではなかったです。ただ、これはHashCode用にカスタマイズされていると思われるため、単純にメモリ番地を取ってきているとかではないかも知れません。)場合によっては、JVMのコードを書き換える必要もあるかも知れませんが、幸い、OpenJDKならオープンソースで、誰でも自由に閲覧して改変して(ライセンスに従って)配付できますので、IDでオブジェクト再利用が可能なオリジナルOpenJDKを作ってくれることを楽しみに待っています(私は作りませんし、使いませんが)。

投稿2020/02/09 03:49

編集2020/02/09 03:54
raccy

総合スコア21735

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

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

退会済みユーザー

退会済みユーザー

2020/02/09 04:04

回答ありがとうございますm(__)m 参考になりました。
Zuishin

2020/02/09 04:07

理解できないのに参考になったんですか? 信じられないことを言いますね。
guest

0

無いのではと思います.

投稿2020/02/06 14:40

jimbe

総合スコア12648

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問