java中的引用对象类型
java中的引用类型分别是强引用,SoftReference,WeakReference,PhantomReference。
我们平常中产生的对象绝大部分是强引用类型,下来来分别介绍。
java强引用对象
Object o = new Object;
String s = "aa";
等等。。。。。。。
特点
当内存不足,JVM开始通过垃圾回收器进行垃圾回收,对于强引用的对象,就算是出现了OOM也不会对该对象进行回收,因为存在引用指向这它,我们平常创建的对象都是强引用对象。要将强引用对象回收,只需引用指向null即可,等待gc回收
java软引用对象(SoftReference)
这里我们启动程序的时候,为了出现内存不足现象,使用了jvm -XX参数。只需vm option配置即可
-XX:InitialHeapSize=10m -XX:MaxHeapSize=10m -XX:+PrintGCDetails
特点
1、当内存充足时,只要软引用对象还有引用指向,就不会被gc回收
2、当内存不充足时,不管软引用对象有没有被指向,都会被回收
public static void main(String[] args) {
// 强引用对象
Object s = new Object();
// 软引用对象
SoftReference<Object> softReference = new SoftReference<>(s);
// 手动GC
System.gc();
System.out.println("内存充足时");
System.out.println(s);
System.out.println(softReference.get());
try {
s = null;
// 当jvm堆内存不足时,会垃圾回收软引用对象
byte[] buffer = new byte[35*1024*1024];
}catch (Error e){
e.printStackTrace();
}finally {
System.out.println("内存不充足时");
System.out.println(s);
System.out.println(softReference.get());
}
}
结果:
[GC (Allocation Failure) [PSYoungGen: 2048K->512K(2560K)] 2048K->842K(9728K), 0.0013049 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (System.gc()) [PSYoungGen: 1084K->512K(2560K)] 1414K->962K(9728K), 0.0010431 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[Full GC (System.gc()) [PSYoungGen: 512K->0K(2560K)] [ParOldGen: 450K->853K(7168K)] 962K->853K(9728K), [Metaspace: 3313K->3313K(1056768K)], 0.0062308 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
内存充足时
java.lang.Object@6b884d57
java.lang.Object@6b884d57
[GC (Allocation Failure) [PSYoungGen: 81K->64K(2560K)] 934K->917K(9728K), 0.0007031 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [PSYoungGen: 64K->128K(2560K)] 917K->981K(9728K), 0.0005246 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[Full GC (Allocation Failure) [PSYoungGen: 128K->0K(2560K)] [ParOldGen: 853K->770K(5632K)] 981K->770K(8192K), [Metaspace: 3317K->3317K(1056768K)], 0.0077545 secs] [Times: user=0.02 sys=0.00, real=0.01 secs]
[GC (Allocation Failure) [PSYoungGen: 0K->0K(2560K)] 770K->770K(9728K), 0.0003751 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[Full GC (Allocation Failure) [PSYoungGen: 0K->0K(2560K)] [ParOldGen: 770K->752K(7168K)] 770K->752K(9728K), [Metaspace: 3317K->3317K(1056768K)], 0.0096544 secs] [Times: user=0.08 sys=0.00, real=0.01 secs]
java.lang.OutOfMemoryError: Java heap space
at com.xiaoxu.test_reference.ReferenceTest.main(ReferenceTest.java:28)
内存不充足时
null
null
Heap
PSYoungGen total 2560K, used 143K [0x00000000ffd00000, 0x0000000100000000, 0x0000000100000000)
eden space 2048K, 7% used [0x00000000ffd00000,0x00000000ffd23ee8,0x00000000fff00000)
from space 512K, 0% used [0x00000000fff00000,0x00000000fff00000,0x00000000fff80000)
to space 512K, 0% used [0x00000000fff80000,0x00000000fff80000,0x0000000100000000)
ParOldGen total 7168K, used 752K [0x00000000ff600000, 0x00000000ffd00000, 0x00000000ffd00000)
object space 7168K, 10% used [0x00000000ff600000,0x00000000ff6bc158,0x00000000ffd00000)
Metaspace used 3360K, capacity 4496K, committed 4864K, reserved 1056768K
class space used 369K, capacity 388K, committed 512K, reserved 1048576K
java弱引用对象(WeakReference)
特点
只要gc就会回收弱引用对象,不管弱引用对象,有没有引用指向
public static void main(String[] args) {
// 强引用对象
Object s = new Object();
// weak引用对象
Reference<Object> weakReference = new WeakReference<>(s);
s=null;
// 手动GC
System.gc();
System.out.println("内存充足时");
System.out.println(s);
System.out.println(weakReference.get());
}
结果:
[GC (Allocation Failure) [PSYoungGen: 2048K->504K(2560K)] 2048K->856K(9728K), 0.0010334 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (System.gc()) [PSYoungGen: 1015K->496K(2560K)] 1368K->976K(9728K), 0.0011791 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[Full GC (System.gc()) [PSYoungGen: 496K->0K(2560K)] [ParOldGen: 480K->849K(7168K)] 976K->849K(9728K), [Metaspace: 3273K->3273K(1056768K)], 0.0051562 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
内存充足时
null
null
Heap
PSYoungGen total 2560K, used 102K [0x00000000ffd00000, 0x0000000100000000, 0x0000000100000000)
eden space 2048K, 5% used [0x00000000ffd00000,0x00000000ffd19b38,0x00000000fff00000)
from space 512K, 0% used [0x00000000fff80000,0x00000000fff80000,0x0000000100000000)
to space 512K, 0% used [0x00000000fff00000,0x00000000fff00000,0x00000000fff80000)
ParOldGen total 7168K, used 849K [0x00000000ff600000, 0x00000000ffd00000, 0x00000000ffd00000)
object space 7168K, 11% used [0x00000000ff600000,0x00000000ff6d4630,0x00000000ffd00000)
Metaspace used 3303K, capacity 4496K, committed 4864K, reserved 1056768K
class space used 361K, capacity 388K, committed 512K, reserved 1048576K
软引用和弱引用的适用场景
需要对图片进行大量缓存
1、如果每次读取图片都从硬盘读取则会严重影响性能
2、如果一次性全部加载到内存中,又可能造成内存溢出
此时使用软引用可以解决这个问题。
设计思路:使用HashMap来保存图片的路径和相应图片对象关联的软引用之间的映射关系,在内存不足时,JVM会自动回收这些缓存图片对象所占的空间,从而有效地避免了OOM的问题
Map<String, SoftReference<BitMap>> imageCache
= new HashMap<String, SoftReference<Bitmap>>();
WeakHashMap存储虚引用对象
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.gc();
System.out.println(map);
}
private static void myWeakHashMap() {
Map<Integer, String> map = new WeakHashMap<>();
Integer key = new Integer(1);
String value = "WeakHashMap";
map.put(key, value);
System.out.println(map);
key = null;
System.gc();
System.out.println(map);
}
一旦回收,map为空
java虚引用对象(PhantomReference)
如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收,它不能单独使用也不能通过它访问对象,虚引用必须和引用队列(ReferenceQueue)联合使用。
虚引用的主要作用是跟踪对象被垃圾回收的状态。仅仅是提供了一种确保对象被finalize以后,做某些事情的机制。