Full GC后,如果JVM内存依然不足,就会回收只有软引用的对象。
JVM发生 OutOfMemoryError 时,也会回收只有软引用的对象。
这段代码,程序会不断抛出OOM异常,抛出异常后年轻代和年老代都会被干净。
package test;
import org.junit.Test;
import java.lang.ref.SoftReference;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
/**
* @author: zyp
* @since: 2021/12/14 下午6:48
*/
public class TestSoftReference {
/**
* 用SoftReference持有一个链表, 一直往链表里面放东西
* 发生OOM时, SoftReference持有的链表就会被回收
* 这时候换一个SoftReference继续放东西
* 整个过程对SoftReference的引用都是强引用
*
* @param
* @return void
* @author zhengyongpan
* @since 2021/12/14 下午7:04
*/
@Test
public void test() {
// 保存软引用
List<SoftReference<List>> refs = new ArrayList<>();
// 当前使用的软引用
SoftReference<List> ref = new SoftReference<>(new LinkedList());
while (true) {
try {
List list = ref.get();
if (list != null) {
list.add(new byte[10240]);
} else {
// 被回收掉了, 换一个SoftReference
System.err.println("被回收掉了");
ref = new SoftReference<>(new LinkedList());
refs.add(ref);
}
} catch (OutOfMemoryError x) {
x.printStackTrace();
// OOM了, 换一个SoftReference
ref = new SoftReference<>(new LinkedList());
refs.add(ref);
}
}
}
}
这段代码,JVM内存不足时,会进行FullGC,将SoftReference持有的byte[]对象进行回收
package test;
import org.junit.Test;
import java.lang.ref.SoftReference;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
/**
* @author: zyp
* @since: 2021/12/14 下午6:48
*/
public class TestSoftReference {
@Test
public void test() throws InterruptedException {
List<SoftReference<byte[]>> list = new LinkedList<>();
int addCount = 0;
int gcCount = 0;
while (true) {
try {
list.add(new SoftReference<>(new byte[1024 * 1024 * 100]));
addCount++;
Iterator<SoftReference<byte[]>> iterator = list.iterator();
int aliveCount = 0;
while (iterator.hasNext()) {
SoftReference<byte[]> next = iterator.next();
if (next.get() != null) {
aliveCount++;
} else {
// 内存不足,被回收掉了
gcCount++;
iterator.remove();
}
}
System.out.println(String.format("生成对象 %s, 回收对象 %s, 存活对象 %s", addCount, gcCount, aliveCount));
} catch (OutOfMemoryError x) {
x.printStackTrace();
}
Thread.sleep(100);
}
}
}