みなさん、こんにちは。JavaResearchInstituteです。
今日、私はあなたに古典的なインタビューの質問をもたらします:強い引用、柔らかい引用、弱い引用、そして誤った引用の違いは何ですか?
ご存知のとおり、JavaではJVMがメモリの割り当てとリカバリを担当します。これはその利点です(使いやすく、プログラムはcを使用するようにメモリについて心配する必要がありません)が、欠点でもあります(十分な柔軟性がありません)。柔軟性のないメモリ操作の問題を解決するために、ソフトリファレンスなどの方法を使用できます。
JDK1.2より前のバージョンでは、オブジェクトがどの変数によっても参照されていない場合、プログラムはそのオブジェクトを使用できなくなります。言い換えると、プログラムは、オブジェクトが到達可能な状態にある場合にのみオブジェクトを使用できます。これは日常生活のように、お店で購入した後、役に立つ場合は永久に保管してください。そうしないと、ゴミ箱に捨てられ、掃除機に持ち去られてしまいます。一般的に、ゴミ箱に捨てられた場合は、拾って再度使用することはできません。
しかし、状況がそれほど単純ではない場合もあります。チキンリブのような味のないアイテムに遭遇し、それらを破棄するのは残念です。この種のアイテムは現在役に立たず、保管するのにスペースが必要ですが、将来使用される可能性があるため、すぐに廃棄するのは費用対効果が高くありません。そのような不要なアイテムの場合、妥協案は次のとおりです。家のスペースが十分な場合は、最初に家に置いておきます。家のスペースが十分でない場合は、家のゴミをすべて取り除いても、必要なものを収容できません。日用品が少ない場合は、これらの不要品を捨ててください。
JDK1.2バージョン以降、オブジェクトの参照は4つのレベルに分割されているため、プログラムはオブジェクトのライフサイクルをより柔軟に制御できます。高から低までの4つのレベルは、ストロングリファレンス、ソフトリファレンス、ウィークリファレンス、ファントムリファレンスです。作成後に3種類のリファレンスに使用する必要があるクラスは次のとおりです。
リファレンスの主なソースコード:
public abstract class Reference<T>{
private T referent;
Reference(T referent) {
this(referent, null);
}
Reference(T referent, ReferenceQueue<? super T> queue) {
this.referent = referent;
this.queue = (queue == null) ? ReferenceQueue.NULL : queue;
}
public T get() {
return this.referent;
}
}
1.1。強い引用
以前に使用した参照のほとんどは、実際には強力な参照であり、最も一般的に使用される参照です。オブジェクトが強い参照を持っている場合、それは不可欠な家庭用品に似ており、ゴミ収集業者はそれを決してリサイクルしません。メモリスペースが不足している場合、Java仮想マシンはOutOfMemoryErrorエラーをスローしてプログラムを異常終了させ、強力な参照を持つオブジェクトを自由に再利用してメモリ不足の問題を解決しません。
static final int KB_1 = 1024;//1kb
static final int MB_1 = 1024 * KB_1;//1mb
static final int MB_5 = 5 * MB_1;//5mb
static final int MB_50 = 50 * MB_1;//50mb
@Test
public void strongReference() throws InterruptedException {
List<byte[]> list = new ArrayList<>();
for (int i = 0; i < 300; i++) {
list.add(new byte[MB_5]);
}
}
list.addに入力されたデータは強く参照されており、ガベージコレクターによって再利用されません。メモリが不足している場合は、oomが報告されます。試してみましょう。
jvm起動パラメータを設定します。最大ヒープメモリは100MBです。
-Xmx100M -Xms100M
出力を実行すると、ヒープメモリがオーバーフローしました。
java.lang.OutOfMemoryError: Java heap space
at ReferenceTest.strongReference(ReferenceTest.java:19)
2.ソフトリファレンス(SoftReference)
オブジェクトにソフト参照しかない場合、それは単なる商品に似ています。メモリスペースが十分である場合、ガベージコレクタはそれを再利用しません。メモリスペースが不十分である場合、ガベージコレクタはこれらのオブジェクトのメモリを再利用します。ガベージコレクターがそれを再利用しない限り、オブジェクトはプログラムによって使用できます。ソフト参照を使用して、メモリに依存するキャッシュを実装できます。
ソフト参照は、参照キュー(ReferenceQueue)と組み合わせて使用できます。ソフト参照によって参照されるオブジェクトがガベージコレクションである場合、Java仮想マシンはそれに関連付けられた参照キューにソフト参照を追加します。
対応するクラスのソフトリファレンス:SoftReference
public class SoftReference<T> extends Reference<T>{
public SoftReference(T referent) {
super(referent);
}
}
ケースコード
@Test
public void softReference() throws InterruptedException {
//创建一个软引用,引用50mb的byte数据
SoftReference<byte[]> sr1 = new SoftReference<>(new byte[MB_50]);//@1
//获取软引用中的数据
System.out.println(sr1.get());
//来个强引用的list
List<byte[]> list = new ArrayList<>();
//选好向list中添加数据,慢慢内存不足,会触发弱引用sr1中引用的50MB byte数据被回收
for (int i = 0; i < 10; i++) {
list.add(new byte[MB_5]);
//获取弱引用中引用的数据
byte[] bytes = sr1.get();
System.out.println(list.size() + ":" + bytes);
TimeUnit.SECONDS.sleep(1);
if (bytes == null) {
break;
}
}
}
次の図は、@ 1コードに対応するメモリ構造です。
効果をテストしてみましょう。最初にjvm起動パラメータを設定します。最大ヒープメモリは、100MBです。
-Xmx100M -Xms100M
操作の結果は次のとおりです。ループが8番目の場合、メモリが不足しています。このとき、sr1でソフト参照された50MBバイトのデータが復元され、sr1.get()メソッドで参照されたデータが取得されます。このとき、nullであり、ガベージ収集されていることを示します。リサイクル
[B@200a570f
1:[B@200a570f
2:[B@200a570f
3:[B@200a570f
4:[B@200a570f
5:[B@200a570f
6:[B@200a570f
7:[B@200a570f
8:null
3.3。弱い参照(WeakReference)
オブジェクトの参照が弱い場合、それは単なる商品に似ています。弱い参照とソフト参照の違いは、弱い参照を持つオブジェクトのみのライフサイクルが短いことです。ガベージコレクタースレッドがその管轄下のメモリ領域をスキャンするプロセスでは、参照が弱いオブジェクトが見つかると、現在のメモリスペースが十分であるかどうかに関係なく、そのメモリが再利用されます。ただし、ガベージコレクターは優先度の低いスレッドであるため、参照が弱いオブジェクトはすぐに見つからない場合があります。
弱い参照は、参照キュー(ReferenceQueue)と組み合わせて使用できます。弱い参照によって参照されるオブジェクトがガベージコレクションである場合、Java仮想マシンはそれに関連付けられた参照キューに弱い参照を追加します。
弱い参照に対応するクラス:WeakReference、ケースコード
@Test
public void weakReference() throws InterruptedException {
//创建一个弱引用,引用50mb的byte数据
WeakReference<byte[]> sr1 = new WeakReference<>(new byte[MB_50]);
//获取软引用中的数据
System.out.println(sr1.get());
System.out.println("触发gc");
System.gc();//触发gc,会导致弱引用中的数据被回收,即sr1中引用的50mb byte被回收
System.out.println("gc完毕");
System.out.println(sr1.get());
}
出力を実行
[B@200a570f
触发gc
gc完毕
null
4.4。ファントムリファレンス(PhantomReference)
名前が示すように、「仮想参照」は仮想参照に他なりません。他のタイプの参照とは異なり、仮想参照はオブジェクトのライフサイクルを決定しません。オブジェクトがファントム参照のみを保持している場合、それは参照がない場合と同じであり、いつでもガベージコレクションされる可能性があります。ファントム参照は、主にゴミ収集されているオブジェクトのアクティビティを追跡するために使用されます。仮想参照とソフト参照およびウィーク参照の違いの1つは、仮想参照を参照キュー(ReferenceQueue)と組み合わせて使用する必要があることです。ガベージコレクターがオブジェクトを再利用しようとしているときに、ファントム参照があることがわかった場合、オブジェクトのメモリを再利用する前に、関連する参照キューにファントム参照を追加します。プログラムは、仮想参照が参照キューに追加されているかどうかを判断することにより、参照されているオブジェクトがガベージコレクションされるかどうかを判断できます。プログラムは、ファントム参照が参照キューに追加されていることを検出すると、参照されたオブジェクトのメモリが再利用される前に、必要なアクションを実行できます。
ファントムリファレンス対応クラス:PhantomReference、ケースコード
@Test
public void phantomReference() throws InterruptedException {
//创建引用队列,当Reference对象引用的数据被回收的时候,Reference对象会被加入到这个队列中
ReferenceQueue<byte[]> referenceQueue = new ReferenceQueue<>();
PhantomReference<byte[]> sr1 = new PhantomReference<>(new byte[MB_50], referenceQueue);
System.out.println(sr1);
//获取软引用中的数据
System.out.println(sr1.get());
System.out.println(referenceQueue.poll());
System.out.println("触发gc");
System.gc();//触发gc
System.out.println("gc完毕");
System.out.println(sr1.get());
System.out.println(referenceQueue.poll());
}
出力を実行
java.lang.ref.PhantomReference@200a570f
null
null
触发gc
gc完毕
null
java.lang.ref.PhantomReference@200a570f
get()メソッドで取得した参照データはすべてnullであり、最初の行と最後の行の結果は同じであることが出力からわかります。仮想参照のデータが再利用された後、仮想参照がキューに追加されていることがわかります。
5.4引用の比較
参照タイプはリサイクル時間目的寿命
オブジェクトの一般的な状態ではない強い参照JVMが終了したときの
ソフト参照の終了メモリが不足している場合、オブジェクトキャッシュメモリが不足している、
弱い参照の終了ガベージコレクションオブジェクトキャッシュGCが実行されている場合、
ファントム参照を終了する不明不明不明不明不明
問題がある交換するメッセージを残すことを歓迎します!
6.6。多分あなたはまだ見たいです
- ステーションBで推奨されるビデオは何ですか?
- 古典的なインタビューの質問:equalsメソッドを書き直すときにhashCodeメソッドを書き直す必要があるのはなぜですか?
- 古典的なインタビューの質問:HashMap 16のデフォルトの容量はなぜですか?
- 古典的なインタビューの質問:ArraylistとLinkedlistの違いは何ですか???
- 古典的なインタビューの質問:NoClassDefFoundErrorとClassNotFoundExceptionの違いは何ですか?
- 古典的なインタビューの質問:Throwable、Exception、Error、RuntimeExceptionの違いは何ですか?
- 古典的なインタビューの質問:試行と最終的にリターンがある場合、コードはどのように実行されますか????
- MySQLが優れているかどうかにかかわらず、何億ものデータに直面しているので、見てみましょう。!
- 古典的なインタビューの質問:ThreadLocalシリアルガン!!
・END・
QRコードをスキャン+フォローしてください