前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >WeakReference

WeakReference

原创
作者头像
reisende
发布2021-10-14 15:02:42
5270
发布2021-10-14 15:02:42
举报
文章被收录于专栏:Leben

导语

本文包括对WeakReference的简介和测试

简介

弱引用,实现了Reference接口

区别于强引用的地方:弱引用的对象会在GC时被回收,无论系统内存是否足够

常用场景:大量对象的创建可能会出现OOM异常,利用弱引用或软引用可以在堆内存不足时回收部分对象,释放空间

简单使用

继承WeakReference类,指定希望用弱引用变量指向的类

代码语言:javascript
复制
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实际就是个指针

代码语言:javascript
复制
PersonWeakReference personWeakReference = new PersonWeakReference(person);

简单测试

利用Junit来构建测试用例

代码语言:javascript
复制
@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对象确实被回收了

如果存在强引用呢

如果某个对象同时被一个普通变量引用和弱引用变量引用

代码语言:javascript
复制
@Test
public void normalObjectWithStrongReferenceTest() {

    Person person = new Person("cloudgu");

    PersonWeakReference personWeakReference = new PersonWeakReference(person);

    System.gc();

    Assert.assertNotNull(personWeakReference.get());
}

gc被成功触发但是该对象并未被回收,强引用的对象不会在gc中被回收

怎么样会产生OOM呢

需要预先设置jvm堆的大小,Xmx500m

一个byte是一个字节,1024*1024个byte就是1mb,创建500次就是500mb

代码语言:javascript
复制
@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在挂掉之前还是做了很多挣扎的

如果都是弱引用还会有OOM吗

把上一个测试例子的对象引用全部换成弱引用

代码语言:javascript
复制
@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 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 导语
  • 简介
  • 简单使用
  • 简单测试
  • 如果存在强引用呢
  • 怎么样会产生OOM呢
  • 如果都是弱引用还会有OOM吗
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档