Java中PhantomReference、WeakReference、SoftReference有什么区别?

Java中有多种引用类型,按照从强到弱的顺序分别如下:

  • 强引用:就是最常见的引用,通过等号赋值就是强引用。
  • 软引用:当内存不足时自动释放引用。一般应用于需要大量内存的缓存程序中。
  • 弱引用:不阻止垃圾回收,当强引用或者软引用都消失时,即使存在弱引用内存也会被释放。
  • 幽灵引用:只引用一个对象的“灵魂”,幽灵引用是不能直接访问的,所以get方法永远返回null。这种引用能阻止JVM释放对象的内存,但是被引用的对象可以finalize。这东西有什么用呢?按照文档中的说法就是用于调整对象之间finalize的顺序。Phantom references are most often used for scheduling pre-mortem cleanup actions in a more flexible way than is possible with the
    Java finalization mechanism.

下面通过代码展现他们之间的不同点。

幽灵引用

为了测试被引用的对象是否存在,只能通过全局的内存使用情况。实验结果是幽灵引用确实能阻止内存被回收,但是finalize在回收的时候才被调用,与文档描述不符。下面请看代码示例:

import java.lang.ref.*;
import java.util.*;

public class Test {
    public static void main(String[] argv) {
        // 查看内存
        // 实验结果是1M
        printMemory();

        // 创建一个非常大的对象,便于查看内存使用率,构建一个幽灵引用
        Object phantomObj = new BigObject();
        ReferenceQueue refQ = new ReferenceQueue();
        PhantomReference phantomRef = new PhantomReference(phantomObj, refQ);

        // 查看内存
        // 实验结果是101M,说明创建的对象大小是100M
        printMemory();

        // 释放强引用,执行内存回收
        // 期望的输出结果应该是BigObject is finalized,实际结果是Phantom released。说明在只有幽灵引用的情况下finalize没有被调用,与文档描述不符。
        phantomObj = null;
        sleep();
        System.gc();System.gc();System.gc();
        System.out.println("Phantom released");

        // 查看内存
        // 实验结果是101M,说明内存没有被回收
        printMemory();

        // 释放幽灵引用,执行内存回收、
        phantomRef = null;
        refQ = null; // 实验证明:这句话如果没有那么内存不会被释放
        sleep(); // 实验证明:如果没有这句话,输出结果呈现随机性,有时候内存没有回收
        System.gc();System.gc();System.gc();

        // 等内存被回收之后,再查看内存
        // 实验结果是1M,说明内存已经被回收了
        printMemory();
    }

    private static void printMemory() {
        System.out.print("The memory usage is: ");
        System.out.println((Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory())/1024.0/1024.0 + "MB");
    }

    private static void sleep() {
        try {
            Thread.sleep(100);
        } catch(InterruptedException ex) {
        }
    }
}

弱引用

下面请看代码示例:

// 构建一个弱引用
String weakObj = new String("Weak Object");
ReferenceQueue weakQueue = new ReferenceQueue();
WeakReference weakReference = new WeakReference(weakObj, weakQueue);
System.out.println("Weak Reference: " + weakReference.get());

// 清空强引用,并执行垃圾回收
weakObj = null;
System.gc();
System.gc();
System.gc();

// 检测弱引用是否可用
// 实验结果:输出结果是null,说明已经被垃圾回收了。
System.out.println("Weak Reference: " + weakReference.get());

软引用

下面请看代码示例:

// 构建一个软引用
String softObj = new String("Soft Object");
ReferenceQueue softQueue = new ReferenceQueue();
SoftReference softRef = new SoftReference(softObj, softQueue);
System.out.println("Soft Reference: " + softRef.get());

// 清空强引用,并执行垃圾回收
softObj = null;
System.gc();
System.gc();
System.gc();

// 检测软引用是否可用
// 输出结果是Soft Object,说明垃圾回收并没有回收软引用。
System.out.println("Soft Reference: " + softRef.get());

// 申请大量内存,直到内存不足
LinkedList li = new LinkedList();
while(true) {
    try {
        li.add(new Object[100000]);
    } catch(OutOfMemoryError e) {
        break;
    }
}
li = null;

// 检测软引用是否可用
// 实验结果:输出null,说明在内存不足之后软引用已经被系统清理了。
System.out.println("Soft Reference: " + softRef.get());

Java中PhantomReference、WeakReference、SoftReference有什么区别?

时间: 2024-08-24 17:20:36

Java中PhantomReference、WeakReference、SoftReference有什么区别?的相关文章

Java中的throw和throws的区别

Java中的throw和throws的区别 1.throw关键字用于方法体内部,而throws关键字用于方法体部的方法声明部分: 2.throw用来抛出一个Throwable类型的异常,而throws用来声明方法可能会抛出某些异常 Java中的throw和throws的区别,布布扣,bubuko.com

java中的hashcode和euqals的区别和联系

一.equals方法的作用 1.默认情况(没有覆盖equals方法)下equals方法都是调用Object类的equals方法,而Object的equals方法主要用于判断对象的内存地址引用是不是同一个地址(是不是同一个对象). 2 .要是类中覆盖了equals方法,那么就要根据具体的代码来确定equals方法的作用了,覆盖后一般都是通过对象的内容是否相等来判断对象是否相等. 没有覆盖equals方法代码如下: [java] view plaincopy //学生类 public class S

Java中PreparedStatement和Statement的用法区别

Java中PreparedStatement和Statement的用法区别 (2012-08-01 11:06:44) 转载▼ 标签: 杂谈   1. PreparedStatement接口继承Statement, PreparedStatement 实例包含已编译的 SQL 语句,所以其执行速度要快于 Statement 对象. 2.作为 Statement 的子类,PreparedStatement 继承了 Statement 的所有功能.三种方法 execute. executeQuery

JAVA中extends 与implements有啥区别?

JAVA中extends 与implements有啥区别?1. 在类的声明中,通过关键字extends来创建一个类的子类.一个类通过关键字implements声明自己使用一个或者多个接口.extends 是继承某个类, 继承之后可以使用父类的方法, 也可以重写父类的方法; implements 是实现多个接口, 接口的方法一般为空的, 必须重写才能使用2.extends是继承父类,只要那个类不是声明为final或者那个类定义为abstract的就能继承,JAVA中不支持多重继承,但是可以用接口

Java中针对 ArrayList和LinkedList 的区别

一般大家都知道ArrayList和LinkedList的大致区别:      1.ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构.      2.对于随机访问get和set,ArrayList觉得优于LinkedList,因为LinkedList要移动指针.      3.对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList要移动数据. ArrayList和LinkedList是两个集合类,用于存储一系列的对象引用

java中Map,List与Set的区别

java中Map,List与Set的区别 目录(?)[+] Set,List,Map的区别 java集合的主要分为三种类型: Set(集) List(列表) Map(映射) 要深入理解集合首先要了解下我们熟悉的数组: 数组是大小固定的,并且同一个数组只能存放类型一样的数据(基本类型/引用类型),而JAVA集合可以存储和操作数目不固定的一组数据. 所有的JAVA集合都位于 java.util包中! JAVA集合只能存放引用类型的的数据,不能存放基本数据类型. 简单说下集合和数组的区别:(参考文章:

Java中equals、==和instanceof的区别

本文转自http://blog.csdn.net/t12x3456/article/details/7341515 (1)对于字符串变量来说,使用“==”和“equals()”方法比较字符串时,其比较方法不同. “==”比较两个变量本身的值,即两个对象在内存中的首地址. “equals()”比较字符串中所包含的内容是否相同. 比如: String s1,s2,s3 = "abc", s4 ="abc" ; s1 = new String("abc"

Java中static final 与 final 的区别(转载)

转自:http://advance0683.iteye.com/blog/1107732 Java中static final 与 final 的区别: 例子: Java代码 import java.util.Random; //这个例子想说明一下static final 与 final的区别 public class StaticAndFinalTest { private static Random rand = new Random(47); //47作为随机种子,为的就是产生随机数. pr

java中 == 和equals的使用与区别

java 的数据类型分为“基本数据类型” 和“引用数据类型”:   --->在基本数据类型的比较中,== 比的就是基本数据类型变量中所保存的值. --->在引用数据类型的比较中,== 才比较的是变量所指向的对象的地址. hashCode()返回该对象的哈希码值,该值通常是一个由该对象的内部地址转换而来的整数,它的实现主要是为了提高哈希表. 我们以引用数据类型为例,因为基本类型比较的是值,简单无须多言. 封装好的String 类型为例: (注意:ObjectL中有方法equals, hashco