前序:
每一种编程语言都有自己操作内存中元素的方式,例如在 C 和 C++ 里是通过指针,而在 java 中则是通过“引用”。在 JDK.1.2 之后,Java 对引用的概念进行了扩充,将引用分为了:强引用(Strong Reference)、软引用(Soft Reference)、弱引用(Weak Reference)、虚引用(Phantom Reference)4 种,这 4 种引用的强度依次减弱
一、强引用
new 对象,构造方法引用对象就是强引用
当JVM内存空间不足,JVM宁愿抛出OutOfMemoryError运行时错误(OOM),使程序异常终止,也不会靠随意回收具有强引用的“存活”对象来解决内存不足的问题。对于一个普通的对象,如果没有其他的引用关系,只要超过了引用的作用域或者显式地将相应(强)引用赋值为 null,就是可以被垃圾收集的了,具体回收时机还是要看垃圾收集策略
Object object = new Object(),当给Object object=null时,强引用解除,此时new Object对象才能被回收
例如:String str = "abc";
List<String> list = new Arraylist<String>();
list.add(str);
举个栗子:
package com.feixiang.platform.stu.jvm.reference.strong;
/**
* Created with IntelliJ IDEA.
* Description: 强引用测试类
*
* @PackageName com.feixiang.platform.stu.jvm.reference.strong
* @Author: ldwtxwhspring
* @Date: 2023-11-29 下午8:04
* @Version: 1.0.0
*/
public class StrongReference {
public static String getUserName(User user){
if (null==user){
System.out.println("被收集");
return null;
}
System.out.println("获取到---》"+user.getName());
return user.getName();
}
public static void main(String[] args) {
User user = new User();
user.setName("张三丰");
getUserName(user);
user = null;
System.gc(); //显示调用GC不一定会被回收,可以多尝试几次,可以修改xms,xmx值让jvm主动去收集
getUserName(user);
}
}
实体类如下:
package com.feixiang.platform.stu.jvm.reference.strong;
/**
* Created with IntelliJ IDEA.
* Description: 实体类
*
* @PackageName com.feixiang.platform.stu.jvm.reference.strong
* @Author: ldwtxwhspring
* @Date: 2023-11-29 下午8:04
* @Version: 1.0.0
*/
public class User {
public Integer id;
public String name;
public String mobile;
public String address;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id=id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name=name;
}
public String getMobile() {
return mobile;
}
public void setMobile(String mobile) {
this.mobile=mobile;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address=address;
}
}
二、软引用
如果一个对象只具有软引用,那就类似于可有可物的生活用品。如果内存空间足够,垃圾回收器就不会回收它,如果内存空间不足了,就会回收这些对象的内存。只要垃圾回收器没有回收它,该对象就可以被程序使用。软引用可用来实现内存敏感的高速缓存
软引用在实际中有重要的应用,例如浏览器的后退按钮
举个栗子:
package com.feixiang.platform.stu.jvm.reference.softreference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
/**
* Created with IntelliJ IDEA.
* Description: 软引用测试类
*
* @PackageName com.feixiang.platform.stu.jvm.reference.softreference
* @Author: ldwtxwhspring
* @Date: 2023-11-29 下午7:54
* @Version: 1.0.0
*/
public class SoftReferenceTest {
public static void soft() throws Exception{
Object obj = new Object();
ReferenceQueue rq = new ReferenceQueue<>();
SoftReference sr = new SoftReference(obj, rq); //创建关于obj的软引用,使用引用队列
System.out.println(sr.get()); //get方法会输出这个obj对象的hashcode
System.out.println(rq.poll()); //输出为null
obj = null;
System.gc();
Thread.sleep(200); //因为finalizer线程优先级很低,所以让线程等待200ms
System.out.println(sr.get()); //因为堆空间没满,可有可无的特性,所以还是会输出这个obj对象的hashcode
System.out.println(rq.poll()); //自然队列为null
}
public static void main(String[] args) {
try {
soft();
} catch (Exception e) {
e.printStackTrace();
}
}
}
三、弱引用
如果一个对象只具有弱引用,那就类似于可有可物的生活用品。弱引用与软引用的区别在于:只具有弱引用的对象拥有更短暂的生命周期。在垃圾回收器线程扫描它 所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存
弱引用可以和一个引用队列(ReferenceQueue)联合使用,如果弱引用所引用的对象被垃圾回收,Java虚拟机就会把这个弱引用加入到与之关联的引用队列中
弱引用在我们的开发中也很常见:最典型的就是大家熟知的:ThreadLocal,WeakHashMap,有兴趣的可以自行研究源码啦
上个栗子吧:
package com.feixiang.platform.stu.jvm.reference.weak;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
/**
* Created with IntelliJ IDEA.
* Description: 弱引用测试类
*
* @PackageName com.feixiang.platform.stu.jvm.reference.weak
* @Author: ldwtxwhspring
* @Date: 2023-11-29 下午7:58
* @Version: 1.0.0
*/
public class WeakReferenceTest {
public static void weak() throws Exception{
Object obj = new Object();
ReferenceQueue rq = new ReferenceQueue<>();
WeakReference wr = new WeakReference(obj,rq);
System.out.println(wr.get());
System.out.println(rq.poll());
obj = null;
System.gc();
Thread.sleep(200);
System.out.println(wr.get()); //这时候会输出null
System.out.println(rq.poll()); //rq队列里也会存放这个弱引用,输出它的hashcode
}
public static void main(String[] args) {
try {
weak();
} catch (Exception e) {
e.printStackTrace();
}
}
}
四、虚引用
虚引用”顾名思义,就是形同虚设,与其他几种引用都不同,虚引用并不会决定对象的生命周期。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收。虚引用主要用来跟踪对象被垃圾回收的活动。虚引用与软引用和弱引用的一个区别在于:虚引用必须和引用队列(ReferenceQueue)联合使用
总结:
在实际程序设计中一般很少使用弱引用与虚引用,使用软用的情况较多,这是因为软引用可以加速JVM对垃圾内存的回收速度,可以维护系统的运行安全,防止内存溢出(OutOfMemory)等问题的产生,学好引用类型也是高效编程的基础哦