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

1. 先上一段代码:

public class ReferenceTest {
public static void main(String[] args){
LinkedList<byte[]> 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 class ReferenceTest {
public static void main(String[] args) {
long beginTime = System.nanoTime();
LinkedList<WeakReference<byte[]>> 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 class ReferenceTest {
public static void main(String[] args) {
long beginTime = System.nanoTime();
LinkedList<SoftReference<byte[]>> 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中的 WeakReference 和 SoftReference的更多相关文章

  1. Java中关于WeakReference和WeakHashMap的理解

    新美大的10月11日的笔试中有一道选择题,让选择函数返回结果,代码如下: private static String test(){ String a = new String("a&quo ...

  2. 谈谈java中的WeakReference

    Java语言中为对象的引用分为了四个级别,分别为 强引用 .软引用.弱引用.虚引用. 本文只针对java中的弱引用进行一些分析,如有出入还请多指正. 在分析弱引用之前,先阐述一个概念:什么是对象可到达 ...

  3. 【转】Java中关于WeakReference和WeakHashMap的理解

    新美大的10月11日的笔试中有一道选择题,让选择函数返回结果,代码如下: private static String test(){ String a = new String("a&quo ...

  4. Java中WeakHashMap实现原理深究

    一.前言 我发现Java很多开源框架都使用了WeakHashMap,刚开始没怎么去注意,只知道它里面存储的值会随时间的推移慢慢减少(在 WeakHashMap 中,当某个“弱键”不再正常使用时,会被从 ...

  5. Java 中 WeakReference 与 SoftReference 的区别?

    虽然 WeakReference 与 SoftReference 都有利于提高 GC 和 内存的效率, 但是 WeakReference ,一旦失去最后一个强引用,就会被 GC 回收,而软引用 虽然不 ...

  6. Java引用总结--StrongReference、SoftReference、WeakReference、PhantomReference

    Java引用总结--StrongReference.SoftReference.WeakReference.PhantomReference 1 Java引用介绍 Java从1.2版本开始引入了4种引 ...

  7. 【转】Java之WeakReference与SoftReference使用讲解

    Java 2 平台引入了 java.lang.ref 包,其中包括的类可以让您引用对象,而不将它们留在内存中.这些类还提供了与垃圾收集器(garbage collector)之间有限的交互. 1.先“ ...

  8. java基础回顾(六)——WeakReference、SoftReference

    在Java里, 当一个对象o被创建时, 它被放在Heap里. 当GC运行的时候, 如果发现没有任何引用指向o, o就会被回收以腾出内存空间. 或者换句话说, 一个对象被回收, 必须满足两个条件: 1) ...

  9. Java的引用StrongReference、 SoftReference、 WeakReference 、PhantomReference

    1. Strong Reference StrongReference 是 Java 的默认引用实现,  它会尽可能长时间的存活于 JVM 内, 当没有任何对象指向它时 GC 执行后将会被回收 @Te ...

随机推荐

  1. GPUImage滤镜之自然饱和度

    自然饱和度”是图像整体的明亮程度,“饱和度”是图像颜色的鲜艳程度. “饱和度”与“色相/饱和度”命令中的“饱和度”选项效果相同,可以增加整个画面的“饱和度”,但如调节到较高数值,图像会产生色彩过饱和从 ...

  2. SpringMVC基础——一个简单的例子

    一.导入 jar 包 二.配置 web.xml 文件 <servlet> <servlet-name>dispatcherServlet</servlet-name> ...

  3. EF增删查改(三)------终极版

    1.Add #region 1.1 新增学生信息(定义成Int类型,返回受影响的行数) /// <summary> /// 新增学生信息 /// </summary> /// ...

  4. 搜索 --- 数独求解 POJ 2676 Sudoku

    Sudoku Problem's Link:   http://poj.org/problem?id=2676 Mean: 略 analyse: 记录所有空位置,判断当前空位置是否可以填某个数,然后直 ...

  5. 详细讲解PHP中缓存技术的应用

    PHP,一门最近几年兴起的web设计脚本语言,由于它的强大和可伸缩性,近几年来得到长足的发展,php相比传统的asp网站,在速度上有绝对的优势,想mssql转6万条数据php如需要40秒,asp不下2 ...

  6. jython 2.7 b3发布

    Jython 2.7b3 Bugs Fixed - [ 2108 ] Cannot set attribute to instances of AST/PythonTree (blocks pyfla ...

  7. OMG 在线思维导图都有开源的

    my-mind在线思维导图 源代码: https://github.com/ondras/my-mind 演示地址: http://my-mind.github.io/ 试了一下,操作上还有些bug, ...

  8. Hibernate Validator

    http://docs.jboss.org/hibernate/validator/4.2/reference/zh-CN/html_single/#example-group-interfaces

  9. php中设定一个全局异常处理。全局catch。默认catch。默认异常处理

    <?php function handleMissedException($e) { echo "Sorry, something is wrong. Please try again ...

  10. Python on VS Code

    install python extension Press F1, and input "ext install python". Then the icon at the le ...