文章目录
- JVM_3_强引用,软引用,弱引用,虚引用分析
-
- 强引用
-
- 概念
- 示例
- 软引用
-
- 概念
- 示例
- 弱引用
-
- 概念
- 示例
- 应用
- WeakHashMap
- 虚引用
-
- 概念
- 示例
-
- 引用队列
- demo
- 对比
JVM_3_强引用,软引用,弱引用,虚引用分析
强引用
概念
- 当内存不足,JVM开始垃圾回收,对于强引用对象,就算出现OOM,也不会对该对象回收.
- 强引用是造成java内存泄漏的主要原因之一
示例
package top.ygy.jvm;
/**
* @Description: TODO(强引用)
* @author yangguangyuan
* @date 2019年6月28日
* obj2未被回收掉
*/
public class StrongReferenceDemo {
public static void main(String[] args) {
Object obj1 = new Object();
Object obj2 = obj1;
obj1 = null;
System.gc();
System.out.println(obj2);
}
}
软引用
概念
- 软引用是一种相对强引用弱化了一些的引用,需要用java.lang.ref.SoftReference类来实现,可以让对象豁免一些垃圾收集.
- 对于只有软引用的对象来说
- 当系统内存充足时,不会被回收.
- 当系统内存不足时,会被回收.
- 用途:软引用通常用在对内存敏感的程序中,比如高速缓存就用到软引用,内存够用就保留,不够用就回收.
示例
package top.ygy.jvm;
import java.lang.ref.SoftReference;
/**
* @Description: TODO(软引用)
* @author yangguangyuan
* @date 2019年6月28日
*/
public class SoftReferenceDemo {
public static void main(String[] args) {
softRef_Memory_NotEnough();
}
/**
* JVM配置,故意生产大对象并配置小内存,让它内存不够用导致OOM,看软引用的回收情况
* -Xms5m -Xmx5m -XX:+PrintGCDetails
*/
public static void softRef_Memory_NotEnough() {
Object o1 = new Object();
SoftReference<Object> softReference = new SoftReference<>(o1);
System.out.println(o1);
System.out.println(softReference.get());
o1 = null;
System.gc();
try {
byte[] byte1 = new byte[30 * 1024 * 1024];
} catch (Exception e) {
e.printStackTrace();
} finally {
System.out.println(o1);
System.out.println(softReference.get());
}
}
}
- 内存够用结果
java.lang.Object@76ccd017
java.lang.Object@76ccd017
null
java.lang.Object@76ccd017
-
内存不够用结果
-Xms5m -Xmx5m -XX:+PrintGCDetails
java.lang.Object@7852e922
java.lang.Object@7852e922
[GC (System.gc()) [PSYoungGen: 841K->488K(1536K)] 841K->592K(5632K), 0.0007545 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[Full GC (System.gc()) [PSYoungGen: 488K->0K(1536K)] [ParOldGen: 104K->558K(4096K)] 592K->558K(5632K), [Metaspace: 2777K->2777K(1056768K)], 0.0048971 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
[GC (Allocation Failure) [PSYoungGen: 0K->0K(1536K)] 558K->558K(5632K), 0.0002058 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [PSYoungGen: 0K->0K(1536K)] 558K->558K(5632K), 0.0001498 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[Full GC (Allocation Failure) [PSYoungGen: 0K->0K(1536K)] [ParOldGen: 558K->558K(4096K)] 558K->558K(5632K), [Metaspace: 2777K->2777K(1056768K)], 0.0018644 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [PSYoungGen: 0K->0K(1536K)] 558K->558K(5632K), 0.0001540 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[Full GC (Allocation Failure) [PSYoungGen: 0K->0K(1536K)] [ParOldGen: 558K->546K(4096K)] 558K->546K(5632K), [Metaspace: 2777K->2777K(1056768K)], 0.0044638 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
null
null
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at top.ygy.jvm.SoftReferenceDemo.softRef_Memory_NotEnough(SoftReferenceDemo.java:31)
at top.ygy.jvm.SoftReferenceDemo.main(SoftReferenceDemo.java:14)
Heap
PSYoungGen total 1536K, used 30K [0x00000000ffe00000, 0x0000000100000000, 0x0000000100000000)
eden space 1024K, 3% used [0x00000000ffe00000,0x00000000ffe07b08,0x00000000fff00000)
from space 512K, 0% used [0x00000000fff80000,0x00000000fff80000,0x0000000100000000)
to space 512K, 0% used [0x00000000fff00000,0x00000000fff00000,0x00000000fff80000)
ParOldGen total 4096K, used 546K [0x00000000ffa00000, 0x00000000ffe00000, 0x00000000ffe00000)
object space 4096K, 13% used [0x00000000ffa00000,0x00000000ffa888f0,0x00000000ffe00000)
Metaspace used 2808K, capacity 4486K, committed 4864K, reserved 1056768K
class space used 303K, capacity 386K, committed 512K, reserved 1048576K
弱引用
概念
- 弱引用需要用java.lang.ref.WeakReference类来实现,它比软引用的生存期更短
- 对于只有弱引用,只要垃圾回收机制一运行,不管JVM内存是否足够,都会回收该对象占用的内存
示例
package top.ygy.jvm;
import java.lang.ref.WeakReference;
/**
* @Description: TODO(弱引用示例)
* @author yangguangyuan
* @date 2019年6月28日
*
*/
public class WeakReferenceDemo {
public static void main(String[] args) {
Object o1 = new Object();
WeakReference<Object> weakReference = new WeakReference<>(o1);
System.out.println(o1);
System.out.println(weakReference.get());
o1 = null;
System.gc();
System.out.println(o1);
System.out.println(weakReference.get());
}
}
应用
- 问题:假如有一个应用需要读取大量的本地图片?
- 分析
- 每次都从硬盘读取影响性能.
- 一次性全部加载到内存中又可能造成内存溢出.
-
解决:使用软引用解决
设计思路:用一个HashMap来保存图片的路径和相应图片对象关联的软引用之间的映射关系,在内存不足时,JVM会自动回收这些缓存图片对象所占用的空间,从而有效的避免了OOM的问题.
WeakHashMap
- 代码
package top.ygy.jvm;
import java.util.HashMap;
import java.util.Map;
import java.util.WeakHashMap;
/**
* @Description: TODO(WeakHashMap)
* @author yangguangyuan
* @date 2019年6月28日
*
*/
public class WeakHashMapDemo {
public static void main(String[] args) {
myHashMap();
System.out.println("**********************************");
myWeakHashMap();
}
private static void myHashMap() {
Map<Integer, String> map = new HashMap<>();
Integer key = new Integer(1);
String value = "HashMap";
map.put(key, value);
System.out.println(map);
key = null;
System.out.println(map);
System.gc();
System.out.println(map + "\t" + map.size());
}
private static void myWeakHashMap() {
Map<Integer, String> map = new WeakHashMap<>();
Integer key = new Integer(2);
String value = "WeakHashMap";
map.put(key, value);
System.out.println(map);
key = null;
System.out.println(map);
System.gc();
System.out.println(map + "\t" + map.size());
}
}
结果:
{1=HashMap}
{1=HashMap}
{1=HashMap} 1
**********************************
{2=WeakHashMap}
{2=WeakHashMap}
{} 0
- 对比
- HashMap:强引用
- WeakHashMap:弱引用
- 应用
- 做高速缓存和对内存敏感的相关业务
虚引用
概念
- 虚引用需要java.lang.ref.PhantomReference类来实现
- “虚引用”顾名思义,就是形同虚设,与其他几种引用都不同,虚引用并不会决定对象的生命周期。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收。
- 虚引用必须和引用队列 (ReferenceQueue)联合使用。当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之 关联的引用队列中。
- 作用:跟踪对象被垃圾回收的状态,仅仅是提供了一种确保对象被finalize以后,做某些事情的机制.
示例
引用队列
package top.ygy.jvm;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.util.WeakHashMap;
public class ReferenceQueueDemo {
public static void main(String[] args) {
Object o1 = new Object();
ReferenceQueue<Object> referenceQueue = new ReferenceQueue<>();
WeakReference<Object> weakReference = new WeakReference<>(o1, referenceQueue);
System.out.println(o1);
System.out.println(weakReference.get());
System.out.println(referenceQueue.poll());
System.out.println("**********************");
o1 = null;
System.gc();
System.out.println(o1);
System.out.println(weakReference.get());
System.out.println(referenceQueue.poll());
}
}
结果:
java.lang.Object@7852e922
java.lang.Object@7852e922
null
**********************
null
null
java.lang.ref.WeakReference@4e25154f
demo
package top.ygy.jvm;
import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;
public class PhantomReferenceDemo {
public static void main(String[] args) {
Object o1 = new Object();
ReferenceQueue<Object> referenceQueue = new ReferenceQueue<>();
PhantomReference<Object> weakReference = new PhantomReference<>(o1, referenceQueue);
System.out.println(o1);
System.out.println(weakReference.get());
System.out.println(referenceQueue.poll());
System.out.println("**********************");
o1 = null;
System.gc();
System.out.println(o1);
System.out.println(weakReference.get());
System.out.println(referenceQueue.poll());
}
}
结果:
java.lang.Object@7852e922
null
null
**********************
null
null
java.lang.ref.PhantomReference@4e25154f
对比
- 强引用:不回收
- 软引用:当系统内存充足时,不会被回收;不足时,会被回收.
- 弱引用:回收
- 虚引用:回收,配合引用队列使用