Java引用类型具体解释

JVM  的垃圾回收器对于不同类型的引用有不同的处理方式。java中对于一个对象来说,仅仅要有引用的存在,它就会一直存在于内存中。假设这种对象越来越多,超出了JVM中的内存总数,JVM就会抛出OutOfMemory错误。尽管垃圾回收的详细执行是由JVM来控制的。可是开发者仍然能够在一定程度上与垃圾回收器进行交互,其目的在于更好的帮助垃圾回收器管理好应用的内存。这种交互方式就是使用JDK1.2 引入的  java.lang.ref包。

强引用(strong reference)

在一般的 Java 程序中,见到最多的就是强引用(strong reference)。如 Date date = newDate(),date  就是一个对象的强引用。对象的强引用能够在程序中到处传递。

非常多情况下,会同一时候有多个引用指向同一个对象。强引用的存在限制了对象在内存中的存活时间。假如对象 A 中包括了一个对象 B 的强引用。那么普通情况下,对象 B  的存活时间就不会短于对象 A。

假设对象 A 没有显式的把对象 B 的引用设为 null  的话,就仅仅有当对象 A 被垃圾回收之后,对象 B  才不再有引用指向它。才可能获得被垃圾回收的机会。

软引用(soft  reference)

软引用(soft  reference)在强度上弱于强引用,通过类SoftReference来表示。

它的作用是告诉垃圾回收器,程序中的哪些对象是不那么重要,当内存不足的时候是能够被临时回收的。当JVM中的内存不足的时候。垃圾回收器会释放那  些仅仅被软引用所指向的对象。

假设所有释放完这些对象之后,内存还不足,才会抛出OutOfMemory错误。软引用很适合于创建缓存。当系统内存不足的时候,缓存中的内容是能够被释放的。

比方考虑一个图像编辑器的程序。该程序会把图像文件的所有内容都读取到内存中。以方便进行处理。而用户也能够同一时候打开 
多个文件。

当同一时候打开的文件过多的时候,就可能造成内存不足。假设使用软引用来指向图像文件内容的话,垃圾回收器就能够在必要的时候回收掉这些内存。

import java.lang.ref.SoftReference;

public class ImageData {
	private String path;
	private SoftReference<byte[]> dataRef;

	public ImageData(String path) {
		this.path = path;
		dataRef = new SoftReference<byte[]>(new byte[0]);
	}

	private byte[] readImage() {
		return new byte[1024 * 1024]; // 省去了读取文件的操作
	}

	public byte[] getData() {
		byte[] dataArray = dataRef.get();
		if (dataArray == null || dataArray.length == 0) {
			dataArray = readImage();
			dataRef = new SoftReference<byte[]>(dataArray);
		}
		return dataArray;
	}
}

在执行上面程序的时候,能够使用  -Xmx  參数来限制JVM可用的内存。

因为软引用所指向的对象可能被回收掉,在通过  get方法来获取软引用所实际指向的对象的时候,总是要检查该对象是否还存活。

弱引用(weak reference)

弱引用(weak reference)在强度上弱于软引用。通过类 WeakReference来  表示。它的作用是引用一个对象,可是并不阻止该对象被回收。假设使用一个强引用的话,仅仅要该引用存在,那么被引用的对象是不能被回收的。弱引用则没有这个问题。在垃圾回收器执行的时候。假设一个对象的全部引用都是弱引用的话。该对象会被回收。

弱引用的作用在于解决强引用所带来的对象之间在存活时间上的耦合关系。

弱引用最常见的用处是在集合类中,尤其在哈希表中。哈希表的接口同意使用不论什么Java对象作为键来使用。当一个键值对被放入到哈希表中之后,哈希表 
对象本身就有了对这些键和值对象的引用。假设这样的引用是强引用的话,那么仅仅要哈希表对象本身还存活。当中所包括的键和值对象是不会被回收的。假设某个存活  时间非常长的哈希表中包括的键值对非常多。终于就有可能消耗掉JVM中所有的内存。

对于这样的情况的解决的方法就是使用弱引用来引用这些对象,这样哈希表中的键和值对象都能被垃圾回收。Java中提供了 WeakHashMap来满足这一常见需求。

虚引用(phantom  reference)

在介绍虚引用之前,要先介绍Java提供的 对象终止化机制(finalization)。

在Object类里面有个 finalize方法。其设计的初衷是在一个对象被真正回收之前,能够用来执行一些清理的工作。由于 Java并没有提供类似 C++的析构函数一样的机制,就通过finalize方法来实现。可是问题在于垃圾回收器的执行时间是不固定的,所以这些清理工作的实际执行时间也是不能预知的。虚引用(phantom  reference)能够解决问题。在创建虚引用 PhantomReference的时候必需要指定一个引用队列。当一个对象的finalize方法已经被调用了之后。这个对象的虚引用会被增加到队列中。

通过检查该队列里面的内容就知道一个对象是不是已经准备要被回收了。

在有些情况下,程序会须要在一个对象的可达到性发生变化的时候得到通知。比方某个对象的强引用都已经不存在了,仅仅剩下软引用或是弱引用。可是还须要对引用本身做一些的处理。典型的情景是在哈希表中。

引用对象是作为WeakHashMap中的键对象的,当其引用的实际对象被垃圾回收之后,就须要把该键值对从哈希表中删除。有了引用队列(ReferenceQueue),就能够方便的获取到这些弱引用对象,将它们从表中删除。在软引用和弱引用对象被加入到队列之前,其对实际对象的引用会被自己主动清空。

通过引用队列的 poll/remove方法就能够分别以非堵塞和堵塞的方式获取队列中的引用对象。

參考文献:

深入理解JVM

Java深度探索

时间: 2024-08-07 19:48:21

Java引用类型具体解释的相关文章

深入理解Java引用类型

深入理解Java引用类型 在Java中类型可分为两大类:值类型与引用类型.值类型就是基本数据类型(如int ,double 等),而引用类型,是指除了基本的变量类型之外的所有类型(如通过 class 定义的类型).所有的类型在内存中都会分配一定的存储空间(形参在使用的时候也会分配存储空间,方法调用完成之后,这块存储空间自动消失), 基本的变量类型只有一块存储空间(分配在stack中), 而引用类型有两块存储空间(一块在stack中,一块在heap中),在函数调用时Java是传值还是传引用,这个估

Java引用类型详解

JVM  的垃圾回收器对于不同类型的引用有不同的处理方式.java中对于一个对象来说,只要有引用的存在,它就会一直存在于内存中.如果这样的对象越来越多,超出了JVM中的内存总数,JVM就会抛出OutOfMemory错误.虽然垃圾回收的具体运行是由JVM来控制的,但是开发人员仍然可以在一定程度上与垃圾回收器进行交互,其目的在于更好的帮助垃圾回收器管理好应用的内存.这种交互方式就是使用JDK1.2 引入的  java.lang.ref包. 强引用(strong reference) 在一般的 Jav

java 引用类型及作用

java 引用类型 0. 引言 Java 中一共有 4 种类型的引用 : StrongReference. SoftReference. WeakReference 以及 PhantomReference , 这 4 种类型的引用与 GC 有着密切的关系. 1. 强引用 (StrongReference) 普通的引用做法,如: String str = "hello"; 只要引用存在就不会被回收,除非手动置为null,或者超出范围,gc才会回收 2. 软引用 (SoftReferenc

Java多线程具体解释

Java多线程具体解释 多线程简单介绍 概述 多线程(multithreading).是指从软件或者硬件上实现多个线程并发运行的技术.具有多线程能力的计算机因有硬件支持而可以在同一时间运行多于一个线程,进而提升总体处理性能.具有这样的能力的系统包含对称多处理机.多核心处理器以及芯片级多处理或同一时候多线程处理器.在一个程序中,这些独立运行的程序片段叫作"线程"(Thread),利用它编程的概念就叫作"多线程处理". 具有多线程能力的计算机因有硬件支持而可以在同一时间

java常用英文解释

java常用名词解释: OO: object-oriented ,面向对象 OOP:object-oriented programming,面向对象编程 Author:JCC Object:对象JDK:Java development kit, java开发工具包 JVM:javavirtual machine ,java虚拟机 Compile:编绎 Run:运行Class:类 System:系统 out:输出 print:打印 line:行 variable:变量 type:类型 get:得到

用java字节码解释i++和++i

用java字节码解释i++和++i - tutuhatec的专栏 - 博客频道 - CSDN.NET 先看4个题目: ①int i = 0; i = i++; ②int i = 0; i = ++i; ③int i = 0; int j = 0; j = i++ + i++; ④ int i = 0; int j = 0; j = i++ + i++ + i++; 每道题里的i和j都是多少? 用myeclipse测试,结果分别是①i = 0,②i = 1,③i = 2,j = 1,④i = 3,

Java集合类具体解释

假设您喜欢这些文章,欢迎点击此处订阅本Blog 集合类说明及差别 Collection ├List │├LinkedList │├ArrayList │└Vector │ └Stack └Set Map ├Hashtable ├HashMap └WeakHashMap Collection接口 Collection是最主要的集合接口,一个Collection代表一组Object,即Collection的元素(Elements).一些 Collection同意同样的元素而还有一些不行.一些能排序而

JAVA Calendar具体解释

(在文章的最后,将会介绍Date类,假设有兴趣,能够直接翻到最后去阅读) 到底什么是一个 Calendar 呢?中文的翻译就是日历,那我们立马能够想到我们生活中有阳(公)历.阴(农)历之分.它们的差别在哪呢? 比方有:月份的定义 - 阳`(公)历 一年12 个月,每一个月的天数各不同:阴(农)历,每一个月固定28天每周的第一天 - 阳(公)历星期日是第一天:阴(农)历,星期一是第一天 实际上,在历史上有着很多种纪元的方法.它们的差异实在太大了,比方说一个人的生日是"八月八日" 那么一种

java泛型具体解释

为什么引入泛型 bug是编程的一部分,我们仅仅能尽自己最大的能力降低出现bug的几率,可是谁也不能保证自己写出的程序不出现不论什么问题. 错误可分为两种:编译时错误与执行时错误.编译时错误在编译时能够发现并排除.而执行时错误具有非常大的不确定性,在程序执行时才干发现.造成的后果可能是灾难性的. 使用泛型能够使错误在编译时被探測到,从而添加程序的健壮性. 来看一个样例: public class Box{ private Object object; public void set(Object