記事のディレクトリ
1.0 4つの参照
JDK1.2前に、Javaの参照定義は非常に伝統的である:基準値は、データストレージの種類を表す場合のメモリ開始アドレスの別の部分で、彼はメモリ参照の作品を表現するために言いました。
JDK1.2後、Javaの概念が拡張参照た、参照は、強い強い参照、ソフトソフト参照弱い弱参照、ファントム偽参照(参照強度が徐々に弱体化)の4種類の分割しましたこれらは、仮想マシンは、これらのオブジェクトと参照オフ回復はメモリ効果の大きさに応じたかどうかを選択する方が合理的であるように、GCのライフサイクル・プロセス内のオブジェクトを識別するために使用されています。
ここのような重要な以下のクラス図を導入します:
2.0、強い参照-StrongReference
十分なメモリ空間がある場合には、Java仮想マシンではなく、リサイクルのためのオブジェクトへの強い参照を持っていません例外OOMをスローしていました。これは、参照内のJavaオブジェクトのほとんどです。新規または作成されたオブジェクトによって反射の使用、すべての強参照している、我々は確認するには、次の手順を使用することができます。
public static void main(String[] args) {
testStrongReference();
}
/*
* @Author ARong
* @Description 测试强引用在内存不足时是否回收(内存不够用也不回收,直接抛OOM)
* -Xmx1024k -XX:+PrintGCDetails
* @Param []
* @return void
**/
private static void testStrongReference() {
Object o1 = new Object();
Object o2 = o1;
o1 = null;
System.out.println("=====GC前=====");
System.out.println(o1);
System.out.println(o2);
// 强制分配1025kb
try {
byte[] allocated = new byte[1024 * 1025];
} catch (Throwable t) {
t.printStackTrace();
}finally {
System.out.println("=====GC后=====");
System.out.println(o1);
System.out.println(o2);
}
}
GCが実行回復できないとき、プログラムを実行して、あなたがオブジェクト参照が強い見ることができる、それが発生します。
[GC (Allocation Failure) [PSYoungGen: 512K->320K(1024K)] 512K->320K(1536K), 0.0008693 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [PSYoungGen: 825K->496K(1024K)] 825K->512K(1536K), 0.0015158 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [PSYoungGen: 994K->512K(1024K)] 1010K->600K(1536K), 0.0009526 secs] [Times: user=0.01 sys=0.00, real=0.00 secs]
=====GC前=====
null
java.lang.Object@5acf9800
[GC (Allocation Failure) [PSYoungGen: 729K->512K(1024K)] 817K->624K(1536K), 0.0020629 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [PSYoungGen: 512K->496K(1024K)] 624K->624K(1536K), 0.0009776 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[Full GC (Allocation Failure) [PSYoungGen: 496K->481K(1024K)] [ParOldGen: 128K->59K(512K)] 624K->540K(1536K), [Metaspace: 3045K->3045K(1056768K)], 0.0049371 secs] [Times: user=0.01 sys=0.00, real=0.01 secs]
[GC (Allocation Failure) [PSYoungGen: 481K->496K(1024K)] 540K->563K(1536K), 0.0008344 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[Full GC (Allocation Failure) [PSYoungGen: 496K->468K(1024K)] [ParOldGen: 67K->56K(512K)] 563K->524K(1536K), [Metaspace: 3045K->3045K(1056768K)], 0.0046858 secs] [Times: user=0.01 sys=0.00, real=0.00 secs]
java.lang.OutOfMemoryError: Java heap space
at jvm_test.ReferenceTest.testStrongReference(ReferenceTest.java:36)
at jvm_test.ReferenceTest.main(ReferenceTest.java:15)
=====GC后=====
null
java.lang.Object@5acf9800
Heap
PSYoungGen total 1024K, used 577K [0x00000007bfe80000, 0x00000007c0000000, 0x00000007c0000000)
eden space 512K, 21% used [0x00000007bfe80000,0x00000007bfe9b4c0,0x00000007bff00000)
from space 512K, 91% used [0x00000007bff80000,0x00000007bfff51d0,0x00000007c0000000)
to space 512K, 0% used [0x00000007bff00000,0x00000007bff00000,0x00000007bff80000)
ParOldGen total 512K, used 56K [0x00000007bfe00000, 0x00000007bfe80000, 0x00000007bfe80000)
object space 512K, 11% used [0x00000007bfe00000,0x00000007bfe0e190,0x00000007bfe80000)
Metaspace used 3127K, capacity 4500K, committed 4864K, reserved 1056768K
class space used 342K, capacity 388K, committed 512K, reserved 1048576K
3.0、ソフト参照-SoftReference
ときに十分なメモリ空間、それが回復しない。十分なメモリ空間がある場合に、リサイクルされます。一般的に回避するOOMするために、リサイクルのためのキャッシュオブジェクトにメモリが不足しているとき、キャッシュを実装するために使用されます。
/*
* @Author ARong
* @Description 测试弱引用在内存不足时是否回收(内存不够则回收,避免OOM) -
* Xmx1024k -XX:+PrintGCDetails
* @Param []
* @return void
**/
private static void testSoftReference() {
Object strongObject = new Object();
SoftReference<Object> softReference = new SoftReference<Object>(strongObject);
strongObject = null;
// GC前
System.out.println("=====GC前=====");
System.out.println(strongObject);
System.out.println(softReference.get());
// 强制分配1025kb
try {
byte[] allocated = new byte[1024 * 1025];
} catch (Throwable t) {
t.printStackTrace();
}finally {
System.out.println("=====GC后=====");
System.out.println(strongObject);
System.out.println(softReference.get());
}
}
プログラムを実行し、十分なメモリ空間で見つけることができ、ソフト参照は、1025キロバイト割り当てられたメモリの後に、ソフト参照するのに十分なメモリがすぐに回収し、回収できないだろう。したがって、ソフト参照は、リサイクルメモリが十分でないメモリが十分である場合、次いで、過剰のキャッシュオブジェクトとして使用することができるローカルキャッシュオブジェクト、、、として使用されるようになっています。
[GC (Allocation Failure) [PSYoungGen: 512K->368K(1024K)] 512K->368K(1536K), 0.0120415 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
[GC (Allocation Failure) [PSYoungGen: 873K->496K(1024K)] 873K->512K(1536K), 0.0011171 secs] [Times: user=0.01 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [PSYoungGen: 994K->512K(1024K)] 1010K->600K(1536K), 0.0007085 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
=====GC前=====
null
java.lang.Object@5acf9800
[GC (Allocation Failure) [PSYoungGen: 773K->512K(1024K)] 861K->704K(1536K), 0.0011383 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
[GC (Allocation Failure) [PSYoungGen: 512K->512K(1024K)] 704K->704K(1536K), 0.0006836 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[Full GC (Allocation Failure) [PSYoungGen: 512K->444K(1024K)] [ParOldGen: 192K->123K(512K)] 704K->567K(1536K), [Metaspace: 3071K->3071K(1056768K)], 0.0043012 secs] [Times: user=0.01 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [PSYoungGen: 444K->480K(1024K)] 567K->603K(1536K), 0.0008256 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[Full GC (Allocation Failure) [PSYoungGen: 480K->436K(1024K)] [ParOldGen: 123K->115K(512K)] 603K->551K(1536K), [Metaspace: 3071K->3071K(1056768K)], 0.0052903 secs] [Times: user=0.01 sys=0.00, real=0.01 secs]
java.lang.OutOfMemoryError: Java heap space
at jvm_test.ReferenceTest.testSoftReference(ReferenceTest.java:63)
at jvm_test.ReferenceTest.main(ReferenceTest.java:16)
=====GC后=====
null
null
Heap
PSYoungGen total 1024K, used 543K [0x00000007bfe80000, 0x00000007c0000000, 0x00000007c0000000)
eden space 512K, 20% used [0x00000007bfe80000,0x00000007bfe9adb0,0x00000007bff00000)
from space 512K, 85% used [0x00000007bff80000,0x00000007bffed208,0x00000007c0000000)
to space 512K, 0% used [0x00000007bff00000,0x00000007bff00000,0x00000007bff80000)
ParOldGen total 512K, used 115K [0x00000007bfe00000, 0x00000007bfe80000, 0x00000007bfe80000)
object space 512K, 22% used [0x00000007bfe00000,0x00000007bfe1cc98,0x00000007bfe80000)
Metaspace used 3199K, capacity 4500K, committed 4864K, reserved 1056768K
class space used 348K, capacity 388K, committed 512K, reserved 1048576K
4.0、弱参照-WeakReference
ソフト参照オブジェクトをスキャンするガベージコレクタはすぐに回収されるたら。
/*
* @Author ARong
* @Description 测试弱引用在内存不足时是否回收(只要扫描到,内存够和不够都回收,避免OOM)
* @Param []
* @return void
**/
private static void testWeakReference() {
Object strongObject = new Object();
WeakReference<Object> weakReference = new WeakReference<Object>(strongObject);
strongObject = null;
System.out.println("=====GC扫描前=====");
System.out.println(strongObject);
System.out.println(weakReference.get());
// GC扫描
System.gc();
System.out.println("=====GC扫描后=====");
System.out.println(strongObject);
System.out.println(weakReference.get());
}
長い弱い参照のようにプログラムした後GC、十分なメモリをスキャンすると、回収されなかった見つけることができます。
[GC (Allocation Failure) [PSYoungGen: 512K->384K(1024K)] 512K->384K(1536K), 0.0020183 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
[GC (Allocation Failure) [PSYoungGen: 889K->496K(1024K)] 889K->520K(1536K), 0.0027958 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
[GC (Allocation Failure) [PSYoungGen: 994K->512K(1024K)] 1018K->608K(1536K), 0.0011595 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
=====GC扫描前=====
null
java.lang.Object@5acf9800
[GC (System.gc()) [PSYoungGen: 765K->496K(1024K)] 861K->656K(1536K), 0.0018561 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[Full GC (System.gc()) [PSYoungGen: 496K->478K(1024K)] [ParOldGen: 160K->86K(512K)] 656K->564K(1536K), [Metaspace: 3069K->3069K(1056768K)], 0.0051843 secs] [Times: user=0.01 sys=0.00, real=0.00 secs]
=====GC扫描后=====
null
null
Heap
PSYoungGen total 1024K, used 569K [0x00000007bfe80000, 0x00000007c0000000, 0x00000007c0000000)
eden space 512K, 17% used [0x00000007bfe80000,0x00000007bfe96d48,0x00000007bff00000)
from space 512K, 93% used [0x00000007bff80000,0x00000007bfff7888,0x00000007c0000000)
to space 512K, 0% used [0x00000007bff00000,0x00000007bff00000,0x00000007bff80000)
ParOldGen total 512K, used 86K [0x00000007bfe00000, 0x00000007bfe80000, 0x00000007bfe80000)
object space 512K, 16% used [0x00000007bfe00000,0x00000007bfe15948,0x00000007bfe80000)
Metaspace used 3177K, capacity 4500K, committed 4864K, reserved 1056768K
class space used 345K, capacity 388K, committed 512K, reserved 1048576K
5.0、仮想基準-PhnatomReference
ファントム参照は、主に参照リサイクルごみ活動をダングリングオブジェクトを追跡するために使用されるオブジェクトのライフサイクルを、決定するものではありません。そして、参照は、組み合わせて使用される仮想キュー(ReferenceQueue)を参照する必要があります。ガベージコレクタは、オブジェクトの準備ができて回復がある場合には、仮想的な基準がある場合は、メモリの前に、この参照が参照に関連付けられた仮想キューに追加されて回収されることが分かりました。キューを参照することができ、プログラムは、仮想オブジェクト参照が回収されたかどうかを知るために、仮想参照番号を変更するために追加されたかどうかを決定する、キュー参照の効果が通知として使用され。
/*
* @Author ARong
* @Description 测试虚引用在内存不足时是否回收
* -Xmx1024k -XX:+PrintGCDetails
* @Param []
* @return void
**/
private static void testPhnatomReference() {
//虚引用并不起任何作用,而是和引用队列一起使用,当虚引用标记的对象被回收时,引用队列中将出现该虚引用
Object strongObject = new Object();
// 引用队列
ReferenceQueue<Object> referenceQueue = new ReferenceQueue<>();
// 创建虚引用,并且与引用队列建立关联
PhantomReference<Object> phantomReference = new PhantomReference<>(strongObject, referenceQueue);
System.out.println("=====GC前=====");
System.out.println(strongObject);
System.out.println(phantomReference.get());
System.out.println(referenceQueue.poll());
strongObject = null;
// 强制分配1025kb, GC
try {
byte[] allocated = new byte[1024 * 1025];
} catch (Throwable t) {
t.printStackTrace();
}finally {
System.out.println("=====GC后=====");
System.out.println(strongObject);
System.out.println(phantomReference.get());
System.out.println(referenceQueue.poll());
}
}
GCが発生する前に見つかったプログラムを実行すると、それが仮想基準オブジェクト参照に存在しない、と参照キューが空です。参照を識別された仮想物体が回収されたときにGCが発生し、仮想参照の存在の主要な意義である、そこに引用された文献対応するキュー:ターゲットが回収されたときに通知を。
GC (Allocation Failure) [PSYoungGen: 512K->384K(1024K)] 512K->384K(1536K), 0.0009170 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [PSYoungGen: 889K->480K(1024K)] 889K->504K(1536K), 0.0010306 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [PSYoungGen: 978K->480K(1024K)] 1002K->608K(1536K), 0.0009136 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
=====GC前=====
java.lang.Object@5acf9800
null
null
[GC (Allocation Failure) [PSYoungGen: 699K->512K(1024K)] 827K->656K(1536K), 0.0007388 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [PSYoungGen: 512K->496K(1024K)] 656K->656K(1536K), 0.0004858 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[Full GC (Allocation Failure) [PSYoungGen: 496K->456K(1024K)] [ParOldGen: 160K->84K(512K)] 656K->541K(1536K), [Metaspace: 3050K->3050K(1056768K)], 0.0041626 secs] [Times: user=0.01 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [PSYoungGen: 456K->496K(1024K)] 541K->596K(1536K), 0.0005543 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[Full GC (Allocation Failure) [PSYoungGen: 496K->444K(1024K)] [ParOldGen: 100K->81K(512K)] 596K->525K(1536K), [Metaspace: 3050K->3050K(1056768K)], 0.0046933 secs] [Times: user=0.01 sys=0.00, real=0.00 secs]
java.lang.OutOfMemoryError: Java heap space
at jvm_test.ReferenceTest.testPhnatomReference(ReferenceTest.java:116)
at jvm_test.ReferenceTest.main(ReferenceTest.java:18)
=====GC后=====
null
null
java.lang.ref.PhantomReference@36baf30c
Heap
PSYoungGen total 1024K, used 516K [0x00000007bfe80000, 0x00000007c0000000, 0x00000007c0000000)
eden space 512K, 14% used [0x00000007bfe80000,0x00000007bfe92178,0x00000007bff00000)
from space 512K, 86% used [0x00000007bff80000,0x00000007bffef030,0x00000007c0000000)
to space 512K, 0% used [0x00000007bff00000,0x00000007bff00000,0x00000007bff80000)
ParOldGen total 512K, used 81K [0x00000007bfe00000, 0x00000007bfe80000, 0x00000007bfe80000)
object space 512K, 15% used [0x00000007bfe00000,0x00000007bfe14560,0x00000007bfe80000)
Metaspace used 3105K, capacity 4500K, committed 4864K, reserved 1056768K
class space used 342K, capacity 388K, committed 512K, reserved 1048576K
6.0まとめ
GCの回復の引用タイプの4種類を超えるご紹介します、その後、次の要約:
-
強い参照(ほとんどのオブジェクト、新しいオブジェクトアウト)
十分なメモリ空間がある場合には、Java仮想マシンではなく、リサイクルのためのオブジェクトへの強い参照を持っていません例外OOMをスローしていました。これは、参照内のJavaオブジェクトのほとんどです。 -
ソフト参照(SoftReference)
ときに十分なメモリ空間、それが回復しない。十分なメモリ空間がある場合に、リサイクルされます。一般的に回避するOOMするために、リサイクルのためのキャッシュオブジェクトにメモリが不足しているとき、キャッシュを実装するために使用されます。 -
弱参照(弱い参照)
ソフト参照オブジェクトをスキャンするガベージコレクタはすぐに回収されるたら。 -
仮想基準(PhantomReference)
オブジェクトのライフサイクルを決定しない仮想基準とは、仮想基準主な目的は、リサイクルゴミの活動を追跡するために使用されます。そして、参照は、組み合わせて使用される仮想キュー(ReferenceQueue)を参照する必要があります。ガベージコレクタは、オブジェクトの準備ができて回復がある場合には、仮想的な基準がある場合は、メモリの前に、この参照が参照に関連付けられた仮想キューに追加されて回収されることが分かりました。キューを参照することができ、プログラムは、仮想オブジェクト参照が回収されたかどうかを知るために、仮想参照番号を変更するために追加されたかどうかを決定する、キュー参照の効果が通知として使用され。
7.0余談-WeakHashMap
参照、のWeakHashMapで見てみましょう4種類以上の違いをご覧ください。一般的にキーが失敗したときに、キャッシュデータを格納するために使用されるのWeakHashMap、値GCは、メモリの使用を節約するために、クリアされます。
2間のコントラスト
/**
* @Auther: ARong
* @Description: 测试WeakHashMap:用作缓存
*/
public class WeakHashMapTest {
public static void main(String[] args) {
hashMapTest();
System.out.println("==========");
weakHashMapTest();
}
/*
* @Author ARong
* @Description 测试HashMap在key为null时发生GC其对应的值是否会回收(不回收)
* @Param []
* @return void
**/
private static void hashMapTest() {
HashMap<Integer, String> hashMap = new HashMap<>();
Integer key = new Integer(1);
String value = "hashMap";
hashMap.put(key, value);
key = null;
System.gc();
System.out.println(hashMap);
}
/*
* @Author ARong
* @Description 测试WeakHashMap在key为null时发生GC其对应的值是否会回收(回收)
* @Param []
* @return void
**/
private static void weakHashMapTest() {
WeakHashMap<Integer, String> weakHashMap = new WeakHashMap<>();
Integer key = new Integer(1);
String value = "hashMap";
weakHashMap.put(key, value);
key = null;
System.gc();
System.out.println(weakHashMap);
}
}
プログラムの実行結果の後
objc[29697]: Class JavaLaunchHelper is implemented in both /Library/Java/JavaVirtualMachines/jdk1.8.0_40.jdk/Contents/Home/bin/java (0x10f0a54c0) and /Library/Java/JavaVirtualMachines/jdk1.8.0_40.jdk/Contents/Home/jre/lib/libinstrument.dylib (0x10f11b4e0). One of the two will be used. Which one is undefined.
{1=hashMap}
==========
{}
キーがNULLに設定された後、HashMapの値がまだ見ることができ、そしてクリア後のWeakHashMapキー、GC値がクリア、低減メモリフットプリントに関連付けられている場合に発生します。