本文包括对WeakReference的简介和测试
弱引用,实现了Reference接口
区别于强引用的地方:弱引用的对象会在GC时被回收,无论系统内存是否足够
常用场景:大量对象的创建可能会出现OOM异常,利用弱引用或软引用可以在堆内存不足时回收部分对象,释放空间
继承WeakReference类,指定希望用弱引用变量指向的类
static class PersonWeakReference extends WeakReference<Person> {
public PersonWeakReference(Person referent) {
super(referent);
}
}
static class Person {
String a;
public Person(String a) {
this.a = a;
}
}
}
创建一个弱引用对象,用personWeakReference变量指向创建的弱引用对象。需要注意的是,当gc发生,person对象被回收时,personWeakRefence变量本身不会变为null,而是通过personWeakReference.get()得到的实际对象变为null。这样看,personWeanRefernce实际就是个指针
PersonWeakReference personWeakReference = new PersonWeakReference(person);
利用Junit来构建测试用例
@Test
public void normalObjectTest() {
PersonWeakReference personWeakReference = new PersonWeakReference(new Person("cloudgu"));
System.gc();
Assert.assertNull(personWeakReference.get());
}
手动触发gc,但是需要注意,System.gc()并不会强制触发gc,而是建议jvm进行gc,因此需要在idea中通过设置jvm参数XX:+PrintGC查看gc情况
运行测试样例
可以看到发生了两次gc,一次young gc,一次full gc
测试通过了,可见通过弱引用指向的person对象确实被回收了
如果某个对象同时被一个普通变量引用和弱引用变量引用
@Test
public void normalObjectWithStrongReferenceTest() {
Person person = new Person("cloudgu");
PersonWeakReference personWeakReference = new PersonWeakReference(person);
System.gc();
Assert.assertNotNull(personWeakReference.get());
}
gc被成功触发但是该对象并未被回收,强引用的对象不会在gc中被回收
需要预先设置jvm堆的大小,Xmx500m
一个byte是一个字节,1024*1024个byte就是1mb,创建500次就是500mb
@Test
public void strongReferenceGcTriggeredBySystemTest() {
List<byte[]> list = new ArrayList<>();
for (int i = 0; i < 500; i++) {
// 1 MB
byte[] bytes = new byte[1024 * 1024];
list.add(bytes);
}
}
运行程序
芜湖,内存溢出了,首先进行了两次新生代的gc(Allocation Failure,因为无法给新对象分配内存),之后产生了一次full gc,之后又是几次不同的gc,可见jvm在挂掉之前还是做了很多挣扎的
把上一个测试例子的对象引用全部换成弱引用
@Test
public void weakReferenceGcTriggeredBySystemTest() {
List<ByteWeakReference> list = new ArrayList<>();
for (int i = 0; i < 500; i++) {
// 1 MB
ByteWeakReference weakReference = new ByteWeakReference(new byte[1024 * 1024]);
list.add(weakReference);
}
list = list.stream().filter(weakReference -> weakReference.get() != null).collect(Collectors.toList());
Assert.assertTrue(list.size() < 500);
}
妙啊,几次young gc就清除掉了大部分内存,可以想像有多少弱引用被清除
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。