开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第1天,点击查看活动详情
前言
java 的引用其实分为 强引用、软引用、弱引用、虚引用。那为什么 java 在设计的时候要分这么多引用类型呢?因为 java 语言是不需要让开发者考虑垃圾回收的,gc 会自己回收,再者便于你控制一个对象的生命周期,由此设计出来了四种引用类型,我们看几个具体介绍
强引用
普通的应用类型,只要有引用指针,GC不会回收 ,例如:
Student student = new Student,想要让GC检测并回收此对象,你需要让它引用Nullstudent = null~~
软引用
软引用我们需要用到jdk自带的SoftReference这个类
SoftReference<T>GC只有在内存不足的时候回收(下面会有测试demo)
弱引用
WeakReference<T>只要触发 GC 对象就会回收常见的比如有 ThreadLocal 内部用的就是这个弱引用
虚引用
虚引用是一种特殊的引用方式,专门用于堆外内存的管理
PhantomReference<T>被回收的对象会放在队列里
实验
我们用代码来简单测试一下软引用
public static void main(String[] args) throws InterruptedException {
final int _8M = 1024 * 1024 * 8;
List<SoftReference<byte[]>> softReferences = new ArrayList<>();
softReferences.add(new SoftReference<>(new byte[_8M]));
System.out.println("添加8M"); // 够用
softReferences.add(new SoftReference<>(new byte[_8M]));
System.out.println("添加8M"); // 够用
softReferences.add(new SoftReference<>(new byte[_8M]));
System.out.println("添加8M"); // 不够用 (会把软引用的对象回收掉)
// 手动执行GC,让它回收
System.gc();
// 这里让主线程等待下,目的是为了让GC立即执行,因为GC这个线程的优先级比较低
TimeUnit.SECONDS.sleep(1);
softReferences.forEach(res -> System.out.println(res.get()));
}
运行之前我们需要配置下程序的环境变量,请看下图,
点击运行绿色箭头,编辑主程序
设置最大运行内存20M,目的是模拟我们的内存空间就20M,这里解释下常用的参数,在我们jvm调优的时候都会用到:
- Xms 是指设定程序启动时占用内存大小。一般来讲,大点,程序会启动的快一点,但是也可能会导致机器暂时间变慢。
- Xmx 是指设定程序运行期间最大可占用的内存大小。如果程序运行需要占用更多的内存,超出了这个设置值,就会抛出OutOfMemory异常。
- Xss 是指设定每个线程的堆栈大小。这个就要依据你的程序,看一个线程大约需要占用多少内存,可能会有多少线程同时运行等。
正常情况下:
添加8M
添加8M
添加8M
[B@312b1dae
[B@7530d0a
[B@27bc2616
内存不够时:GC会主动释放内存,所以前面的两个都为Null了
添加8M
添加8M
添加8M
null
null
[B@312b1dae
应用场景
强引用:普通用法
软引用:缓存
弱引用:防止一些map中内存泄漏的,例如threadlocal中的内存泄漏
虚引用:jvm内部专门管理直接内存的