1.强引用
package com.cjian.threadlocal;
import java.io.IOException;
/**
* @description:强引用
* @author: cWX969834
* @time: 2020/11/12 18:52
*/
public class NormalReferenceTest {
public static void main(String[] args) throws IOException {
Person p = new Person();//类似这种直接指向一个对象的的为强引用
p = null;// p与new Person()之间的强应用被断开,此时,new Person() 是一个垃圾
System.gc();
//阻塞main线程,给垃圾回收线程时间去执行
System.in.read();
}
static class Person{
@Override
protected void finalize() throws Throwable {
//一个对象被回收的时候,会调用到该方法
System.out.println("finalize...");
//官方是不建议我们重写该方法的,该方法如果执行时间过长,会使对象回收速度变慢,会导致FGC、OOM
}
}
}
输出:
finalize...
2.软引用
package com.cjian.threadlocal;
import java.lang.ref.SoftReference;
/**
* @description:软引用
* @author: cWX969834
* @time: 2020/11/12 19:00
*/
public class SoftReferenceTest {
public static void main(String[] args) throws InterruptedException {
//sr 与new SoftReference之间还是一个强引用的,new SoftReference 与new byte[1014*1014*10]之间是一个软引用
SoftReference<byte[]> sr = new SoftReference<>(new byte[1014*1014*10]);
//获取
System.out.println(sr.get());
System.gc();
Thread.sleep(1000);
System.out.println(sr.get());
//再分配一个数组,我们通过vm参数将堆内存大小设置为20M,由于之前sr已经占据了10M,这里会不够分,才会去回收sr
//这里就又是一个强引用
//byte[] b = new byte[1014*1014*15];
//通过验证的得知,内存够时,软引用不会被回收,内存不够用时,软引用才会被回收
//再次获取sr
//System.out.println("-->"+sr.get());
}
}
输出:
[B@29453f44
[B@29453f44
当我们放开最下面的两行代码的时候,并将堆最大值设为24M(-Xmx24M)时,输出如下:
PS:这里在验证的时候本想着设置20M的,但是报了OOM,可能是因为堆内有其他的一些对象,占用了一点内存,调制24M,结果才正确
[B@29453f44
[B@29453f44
-->null
软引用非常适合做缓存
3.弱引用
package com.cjian.threadlocal;
import java.lang.ref.WeakReference;
/**
* @description:弱引用
* @author: cWX969834
* @time: 2020/11/12 18:50
*/
public class WeakReferenceTest {
public static void main(String[] args) {
WeakReference<Person> wr = new WeakReference<>(new Person());
System.out.println(wr.get());
System.gc();
System.out.println(wr.get());
}
static class Person{
@Override
protected void finalize() throws Throwable {
//一个对象被回收的时候,会调用到该方法
System.out.println("finalize...");
//官方是不建议我们重写该方法的,该方法如果执行时间过长,会使对象回收速度变慢,会导致FGC、OOM
}
}
}
输出:
com.cjian.threadlocal.WeakReferenceTest$Person@29453f44
null
finalize...
可知,弱引用在垃圾回收的时候是直接被回收的,那有什么用呢?这也是难点!
4.虚引用
了解即可,知识补充可去学习Netty
package com.cjian.threadlocal;
import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;
import java.util.LinkedList;
import java.util.List;
/**
* @description:虚引用
* @author: cWX969834
* @time: 2020/11/12 19:59
*/
public class PhantomReferenceTest {
private static final List<Object> LIST = new LinkedList<>();
private static final ReferenceQueue<Person> QUEUE = new ReferenceQueue<>();
public static void main(String[] args) {
PhantomReference<Person> pr = new PhantomReference<>(new Person(), QUEUE);
System.out.println(pr.get());
}
static class Person{
@Override
protected void finalize() throws Throwable {
//一个对象被回收的时候,会调用到该方法
System.out.println("finalize...");
//官方是不建议我们重写该方法的,该方法如果执行时间过长,会使对象回收速度变慢,会导致FGC、OOM
}
}
}
输出:
null
这是什么鬼?拿都拿不到,有啥用?
管理直接内存:
虚引用指向的对象在被回收的时候,会将引用放在一个队列里(存信号),然后回收的时候是通过队列回收的,需要JVM特殊处理(回收这个引用指向的直接内存)
package com.cjian.threadlocal;
import java.lang.ref.PhantomReference;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.util.LinkedList;
import java.util.List;
/**
* @description:虚引用
* @author: cWX969834
* @time: 2020/11/12 19:59
*/
public class PhantomReferenceTest {
private static final List<Object> LIST = new LinkedList<>();
private static final ReferenceQueue<Person> QUEUE = new ReferenceQueue<>();
public static void main(String[] args) {
PhantomReference<Person> pr = new PhantomReference<>(new Person(), QUEUE);
System.out.println(pr.get());
new Thread(()->{
while(true){
LIST.add(new byte[1024*1024]);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("--->"+pr.get());
}
}).start();
new Thread(()->{
while(true){
Reference<? extends Person> poll = QUEUE.poll();
if(poll!=null){
System.out.println("虚引用被jvm回收了--->"+poll);
}
}
}).start();
}
static class Person{
@Override
protected void finalize() throws Throwable {
//一个对象被回收的时候,会调用到该方法
System.out.println("finalize...");
//官方是不建议我们重写该方法的,该方法如果执行时间过长,会使对象回收速度变慢,会导致FGC、OOM
}
}
}
null
--->null
--->null
--->null
--->null
--->null
--->null
--->null
--->null
--->null
--->null
finalize...
--->null
--->null
--->null
--->null
--->null
虚引用被jvm回收了--->java.lang.ref.PhantomReference@6a77f9ce
--->null
--->null
Exception in thread "Thread-0" java.lang.OutOfMemoryError: Java heap space
at com.cjian.threadlocal.PhantomReferenceTest.lambda$main$0(PhantomReferenceTest.java:28)
at com.cjian.threadlocal.PhantomReferenceTest$$Lambda$1/1828972342.run(Unknown Source)
at java.lang.Thread.run(Thread.java:748)