我们知道Java语言中没有指针,取而代之的是引用reference。Java中的引用又可以分为四种:强引用,弱引用(WeakReference),软引用(SoftReference),虚引用(PhantomReference)。其中强引用,就是我们平时使用的最多的最普通的引用,虚引用一般我们是没有机会使用到的。所以我们主要了解下 WeakReference 和 SoftReference(除了上面说的四种引用之外,其实还有一种引用——原子引用AtomicReference,用于并发编程环境)。

1. 先上一段代码:

public classReferenceTest {public static voidmain(String[] args){LinkedList list = new LinkedList<>();for(int i=0; i<1024; i++){

list.add(new byte[1024*1024]);

}

}

}

上面的代码会抛出:Exception in thread "main" java.lang.OutOfMemoryError: Java heap space

堆内存溢出。因为我们不断的在堆上分配一个 1M 大小的 byte[]对象,并且将该引用加入到 list 中,循环1024次,需要占用 1G 的堆内存,从而导致 heap space OutOfMemory.

2.我们使用 WeekReference 对代码进行修改:

public classReferenceTest {public static voidmain(String[] args) {long beginTime =System.nanoTime();LinkedList> list = new LinkedList<>();for (int i = 0; i < 1024; i++) {

list.add(new WeakReference<>(new byte[1024 * 1024]));

}long endTime =System.nanoTime();

System.out.println(endTime-beginTime);

}

}

输出的结果:195947704 (0.19秒)

我们发现堆内存溢出的错误没有了。这是什么原因呢。因为我们使用了 弱引用WeekReference 来引用堆上的 1M 的byte[]对象,而弱引用WeekReference引用的对象,如果仅仅只被弱引用,而没有被强引用的话,在下一次GC时,就会回收该对象占用的内存,所以不会内存溢出。

3. 我们使用 SoftReference 对代码进行修改:

public classReferenceTest {public static voidmain(String[] args) {long beginTime =System.nanoTime();LinkedList> list = new LinkedList<>();for (int i = 0; i < 1024; i++) {

list.add(new SoftReference<>(new byte[1024 * 1024]));

}long endTime =System.nanoTime();

System.out.println(endTime-beginTime);

}

}

输出结果:1499904286 (1.5秒)

我们发现堆内存溢出的错误也没有了。因为我们使用了 软引用SoftReference 来引用堆上的 1M 的byte[]对象,而软引用SoftReference引用的对象,如果仅仅只被软引用,而没有被强引用的话,在内存空间不足时,GC 就会回收该对象占用的内存,所以不会内存溢出。

但是我们注意到 采用WeekReference和采用SoftReference所花费的时间,有接近10被的差距。原因应该是,SoftReference只有在内存空间不足时,GC才会回收对象占用的空间,而这时进行的是 full GC,full GC会导致 STW 程序暂停,所以花费的时间过多。

4. 总结

强引用:只要堆上的对象,被至少一个强引用所指向,那么GC就不会回收该对象的内存空间。

弱引用:只要堆上的对象仅仅只被弱引用所指向,不管当前内存空间是否足够,下次GC都会回收对象的内存空间。

软引用:只要堆上的对象仅仅只被软引用所指向,并且当内存空间不足时,GC才会回收对象的内存空间。

WeakReference 和 SoftReference一般使用在构造一个缓存系统,比如使用一个map来构造。因为缓存系统是一个“全生命期”的对象,系统停止,缓存对象才会被销毁,所以当我们不断的想缓存对象中添加对象时,那么就会导致该缓存对象map所引用的对象越来越多,而因为是强引用,这些被放进map缓存了的对象不能被GC所回收,那么就导致系统堆内存占用会越来越大,从而最终导致内存溢出。

那么此时我们就可以使用 WeakReference 或 SoftReference了,将强引用通过WeakReference 和 SoftReference 包装之后,变成弱引用和软引用,那么当缓存中的对象,仅仅被缓存map所引用时,那么分别在下次GC和内存不足GC时就会回收这些对象占用的内存。其实JDK给我们提供了一个专门的类:WeakHashMap ,弱引用的hashMap,所以构造缓存系统是,我们可以考虑使用它。

其实这里引出了另外一个问题,jdk中众多的map,我们应该如何进行选择:

HashMap

ConcurrentHashMap

TreeMap

WeakHashMap

LinkedHashMap

Collections.synchronizedMap

Hashtable

等等。我们在选择一个map时,应该好好的考虑下,那个更加适合我们的需求。

java中的softreference_Java中的 WeakReference 和 SoftReference相关推荐

  1. java中的softreference_Java中内存优化的SoftReference 和 WeakReference浅析

    一.引用对象类型定义 首先,引用对象在Java定义中有三种类型,从弱到强依次为:软引用.弱引用与虚引用,三种级别也各有所不同(软引用>弱引用).本文浅析下软引用与弱引用.大概的解释,软引用适合应 ...

  2. java中的softreference_Java中的SoftReference和WeakReference有什么区别?

    问题 Java中的SoftReference和WeakReference有什么区别?它们有什么不同? #1 热门回答(806 赞) 弱引用弱引用,简单地说,是一个不足以强制对象保留在内存中的引用.弱引 ...

  3. Java中WeakReference,SoftReference,PhantomReference和Strong Reference之间的区别

    很长一段时间以来,WeakReference和SoftReference都已添加到Java API中,但是并不是每个Java程序员都熟悉它. 这意味着在Java中使用WeakReference和Sof ...

  4. Java中的 WeakReference 和 SoftReference

    我们知道Java语言中没有指针,取而代之的是引用reference.Java中的引用又可以分为四种:强引用,弱引用(WeakReference),软引用(SoftReference),虚引用(Phan ...

  5. java system.runfinalization()_Android中缓存理解(一)

    Java GarbageCollection(GC) Java不能像C/C++那样直接对内存进行操作(内存分配和垃圾回收). 由于JVM会自动回收(GC),Java程序员很难控制JVM的内存回收,只能 ...

  6. weakreference_Java中WeakReference,SoftReference,PhantomReference和Strong Reference之间的区别...

    weakreference 很长一段时间以来,WeakReference和SoftReference都已添加到Java API中,但是并不是每个Java程序员都熟悉它. 这意味着在Java中使用Wea ...

  7. java string 占位符_驳《阿里「Java开发手册」中的1个bug》?

    前两天写了一篇关于<阿里Java开发手册中的 1 个bug>的文章,评论区有点炸锅了,基本分为两派,支持老王的和质疑老王的. 首先来说,无论是那一方,我都真诚的感谢你们.特别是「二师兄」, ...

  8. word录入表单数据 java 导入系统,java导入excel | 怎么把excel中的数据批量导入到word中的表格中...

    用javascript怎么实现把excel中的数据批量导入到数据库表中 这个js不能直接实现吧 我们程序用到 先读取excel内容转换成数组 然后放到页面上 再提交表单 储存 MySql如何批量添加数 ...

  9. java mod %区别_Java中 % 与Math.floorMod() 区别详解

    %为取余(rem),Math.floorMod()为取模(mod) 取余取模有什么区别呢? 对于整型数a,b来说,取模运算或者取余运算的方法都是: 1.求 整数商: c = a/b; 2.计算模或者余 ...

最新文章

  1. 前端开发之走进Vue.js
  2. GitHub 的 Action 接入 Stryker.NET 进行自动化测试单元测试鲁棒性
  3. 如何确定autosar的版本_AUTOSAR编码指南(中文版)
  4. OpenCV在jni中使用混合高斯背景模型出现的通道匹配错误
  5. SACC2019架构师大会PPT合集
  6. MIT机器人轻松搞定桌游叠叠乐:你能玩过它算我输 | 《科学》子刊
  7. mysql报错:Host ***.***.***.*** is not allowed to connect to this MySQL server
  8. java跳跳球代码,README.md
  9. html在新网页输出结果是,JavaScript考试试卷
  10. c语言中文网pdf免费下载,C语言中文网VIP教程11.9.pdf
  11. 无耗传输线 matlab,基于Matlab模块化的微波工程Smith圆图辅助教学方法
  12. 传奇世界修改服务器时间,《传奇世界手游时长版》测试结束公告
  13. html什么是一级标题,一级标题是什么(论文一二三级标题范本)
  14. 计算机程序设计c++ 9-7:类的抽象描述举例-汽车类及圆类设计
  15. c++ sort 转载
  16. mysql from多表顺序_数据库 from 表的顺序
  17. 数据库删除字段指定字符前面或者后面的字符串
  18. PTX-PEG-TCO 紫杉醇-聚乙二醇-反式环辛烯
  19. Windows下反(反)调试技术汇总
  20. 对BRDF模型的自我理解

热门文章

  1. 【教程】Spire.Doc系列教程(3):C# Word查找和替换功能
  2. 13 常见CHIP封装的创建
  3. Vue 项目运行完成后自动打开浏览器【多种方法】
  4. 计算机代码清单目录,搜索文件夹并生成目录清单
  5. 微信公众号三方平台开发【获取授权方的授权信息以及基本信息】
  6. Java判断三个球的大中小_玩进球数有门道 三种判断大小球的典型方法
  7. Python扑克牌程序
  8. 毕业季,成为3D建模师一定要认真考虑
  9. 制作启动盘及安装系统
  10. 文案怎么写?文案范例一次学会!