**对引用简单理解:Person p = new Person(); 其中 = 左边是引用,存在栈中; = 号右边是对象,在堆里。
引用整体架构图
四种引用特点
- 强引用:默认,即使OOM,JVM也不会GC这种引用,除非显示的赋值为 null
- 软引用:内存够,不收,内存不够,收。通常用在对内存敏感的程序中,例如:高速缓存。
- 弱引用:只要GC一运行,不管内存够不够,都收...
- 虚引用:幽灵引用,形同虚设...
虚引用
- 不决定对象的生命周期
- 如果一个对象仅持有虚引用,那就跟没有任何引用一样,在任何时候都可能被GC回收
- 它不能单独使用,也不能通过它访问对象
- 必须和引用队列(ReferenceQueue)联合使用
虚引用的主要作用:
- 跟踪对象被GC回收的状态,仅仅是提供了一种确保对象被finalize之后,做某些事情的机制;
- 虚引用的 get 方法总时返回 null ,因此无法访问对应的引用对象。其意义在于说明一个对象已经进入 finalization 阶段,可以被GC回收,用来实现比 finalization 机制更灵活的回收操作;
- 设置虚引用的唯一目的,就是在这个对象被收集器回收的时候,收到一个系统通知,或者后续添加进一步的处理;
- Java 技术允许使用 finalize() 方法在垃圾收集器将对象从内存中清除出去之前做一些必要的清理工作。
四种引用模式示例代码如下:结合 四种引用特点 ,一目了然
public static void main(String[] args) {
ReferenceQueue referenceQueue = new ReferenceQueue();
/**
* 不加任何修饰,即默认强引用
*/
System.out.println("********** 强引用 **********");
Integer key = new Integer(1);
HashMap hashMap = new HashMap();
hashMap.put(key,"HashMap");
System.out.println("HashMap:"+hashMap);
key = null;
System.gc();
System.out.println("===== GC =====");
System.out.println("HashMap:"+hashMap);
/**
* 弱引用
*/
System.out.println("\n********** 弱引用 **********");
Object o1= new Object();
WeakReference weakReference = new WeakReference(o1,referenceQueue);
System.out.println("o1 :"+o1);
System.out.println("weakReference.get():"+weakReference.get());
System.out.println("引用队列:"+referenceQueue.poll());
o1 = null;
System.gc();
System.out.println("===== GC =====");
System.out.println("o1 :"+o1);
System.out.println("weakReference.get():"+weakReference.get());
System.out.println("引用队列:"+referenceQueue.poll());
/**
* 虚引用
*/
System.out.println("\n********** 虚引用 **********");
Object o2= new Object();
PhantomReference phantomReference = new PhantomReference(o2,referenceQueue);
System.out.println("o2 :"+o2);
System.out.println("phantomReference.get():"+phantomReference.get());
System.out.println("引用队列:"+referenceQueue.poll());
o2 = null;
System.gc();
System.out.println("===== GC =====");
System.out.println("o2 :"+o2);
System.out.println("phantomReference.get():"+phantomReference.get());
System.out.println("引用队列:"+referenceQueue.poll());
/**
* 软引用
* -Xms5m | -Xmx5m | -XX:PrintGCDetails
* 分配最大空间5兆 | 启动最小空间5兆 | 打印GC详细日志
*/
System.out.println("\n********** 软引用 **********");
Object o3= new Object();
SoftReference softReference = new SoftReference(o3,referenceQueue);
System.out.println("o3 :"+o3);
System.out.println("softReference.get():"+softReference.get());
System.out.println("引用队列:"+referenceQueue.poll());
o3 = null;
System.out.println("o3 :"+o3);
System.out.println("softReference.get():"+softReference.get());
System.out.println("引用队列:"+referenceQueue.poll());
try {
byte[] b = new byte[30*1024*1024];
}catch (Exception e){
e.printStackTrace();
}finally {
System.out.println("softReference.get():"+softReference.get());
System.out.println("引用队列:"+referenceQueue.poll());
}
}
-----打印日志-----
********** 强引用 **********
HashMap:{1=HashMap}
===== GC =====
HashMap:{1=HashMap}
********** 弱引用 **********
o1 :java.lang.Object@6ff3c5b5
weakReference.get():java.lang.Object@6ff3c5b5
引用队列:null
===== GC =====
o1 :null
weakReference.get():null
引用队列:java.lang.ref.WeakReference@3764951d
********** 虚引用 **********
o2 :java.lang.Object@4b1210ee
phantomReference.get():null
引用队列:null
===== GC =====
o2 :null
phantomReference.get():null
引用队列:java.lang.ref.PhantomReference@4d7e1886
********** 软引用 **********
o3 :java.lang.Object@3cd1a2f1
softReference.get():java.lang.Object@3cd1a2f1
引用队列:null
o3 :null
softReference.get():java.lang.Object@3cd1a2f1
引用队列:null
softReference.get():null
引用队列:java.lang.ref.SoftReference@2f0e140b
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at com.example.lpy.myapplication.javatest.MyReferenceDemo.main(MyReferenceDemo.java:85)
引用队列:
- ReferenceQueue:引用的对象在回收时都会先入引用队列,是用来配合这几种引用工作的;
- 当关联的引用队列中有数据时,意味着引用指向的堆内存中的对象被回收。通过这种方式,JVM允许我们在对象被销毁之后,做一些我们自己想做的事。例如发送一个通知等。
上述代码 “软引用” 模块 VM 大小配置方法如下: