Java中四种引用:强、软、弱、虚引用
这篇文章非常棒:http://alinazh.blog.51cto.com/5459270/1276173
Java中四种引用:强、软、弱、虚引用
1.1、强引用
当我们使用new 这个关键字创建对象时,被创建的对象就是强引用,如Object object = new Object() 这个Object()就是一个强引用。如果一个对象具有强引用,垃圾回收器就不会去回收有强引用的对象,如当jvm内存不足时,具备强引用的对象,虚拟机宁可会报内存空间不足的异常来终止程序,也不会靠垃圾回收器去回收该对象来解决内存。
1.2、软引用
如果一个对象只具有软引用,则内存空间足够,垃圾回收器就不会回收它;
如果内存空间不足了,就会回收这些对象的内存。
只要垃圾回收器没有回收它,该对象就可以被程序使用。
软引用可用来实现内存敏感的高速缓存(下文给出示例)。
软引用可以和一个引用队列(ReferenceQueue)关联使用:
- String str = new String("test");
- ReferenceQueue<String> rq = new ReferenceQueue<>();
- SoftReference sf = new SoftReference(str,rq);
如果软引用(sf)所引用的对象(str)被垃圾回收器回收,Java虚拟机就会把这个软引用(sf)加入到与之关联的引用队列(rq)中,之后可以通过循环调用rq的poll()方法,来清除无用的软引用对象(sf)
如果软引用所引用的对象(str)还没有被垃圾回收器回收,则可以通过这个引用(sf)的get()方法重新获得对引用对象(str)的强引用.
1.3、弱引用
如果一个对象只具有弱引用,只要垃圾回收器在自己的内存空间中线程检测到了,就会立即被回收,对应内存也会被释放掉。相比软引用弱引用的生命周期要比软引用短很多。不过,如果垃圾回收器是一个优先级很低的线程,也不一定会很快就会释放掉软引用的内存。
通俗的来说就是:发生GC时必定回收弱引用指向的内存空间。
示例代码:
- public static void main(String[] args) {
- String string = new String("test");
- ReferenceQueue<String> rq = new ReferenceQueue<>();
- WeakReference<String> wr = new WeakReference<String>(string,rq);
- System.out.println(wr.get());
- string = null;
- System.gc();
- System.out.println(wr.get());
- }
运行结果:
- test
- null
1.4、虚引用
又称为幽灵引用或幻影引用,虚引用既不会影响对象的生命周期,也无法通过虚引用来获取对象实例,仅用于在发生GC时接收一个系统通知。
相关问题一、若一个对象的引用类型有多个,那到底如何判断它的可达性呢?其实规则如下:
1. 单条引用链的可达性以最弱的一个引用类型来决定;
2. 多条引用链的可达性以最强的一个引用类型来决定;
我们假设图2中引用①和③为强引用,⑤为软引用,⑦为弱引用,对于对象5按照这两个判断原则,路径①-⑤取最弱的引用⑤,因此该路径对对象5的引用为软引用。同样,③-⑦为弱引用。在这两条路径之间取最强的引用,于是对象5是一个软可及对象(当将要发生OOM时则会被回收掉)。
相关问题二、与引用相关联的引用队列的作用是什么
- ReferenceQueue queue = new ReferenceQueue();
- SoftReference ref=new SoftReference(aMyObject, queue);
- SoftReference ref = null;
- while ((ref = (EmployeeRef) q.poll()) != null) {
- // 清除ref
- }
- EmployeeCache 类:
- import java.lang.ref.ReferenceQueue;
- import java.lang.ref.SoftReference;
- import java.util.Hashtable;
- public class EmployeeCache {
- static private EmployeeCache cache;
- private Hashtable<String, EmployeeRef> employeeRefs;
- private ReferenceQueue<Employee> q;
- private class EmployeeRef extends SoftReference<Employee>{
- private String _key="";
- public EmployeeRef(Employee em,ReferenceQueue<Employee> q) {
- super(em,q);
- _key=em.getId();
- }
- }
- private EmployeeCache() {
- employeeRefs = new Hashtable<>();
- q = new ReferenceQueue<>();
- }
- public static EmployeeCache getInstance(){
- if(cache==null){
- cache = new EmployeeCache();
- }
- return cache;
- }
- private void cacheEmployee(Employee em){
- cleanCache();
- EmployeeRef ref = new EmployeeRef(em, q);
- employeeRefs.put(em.getId(), ref);
- }
- public Employee getEmployee(String id){
- Employee employee = null;
- if(employeeRefs.contains(id)){
- EmployeeRef ref = employeeRefs.get(id);
- employee = ref.get();
- }
- if(employee == null){
- employee = new Employee(id);
- System.out.println("从信息中心获取新的对象");
- this.cacheEmployee(employee);
- }
- return employee;
- }
- private void cleanCache() {
- EmployeeRef ref = null;
- while((ref=(EmployeeRef) q.poll())!=null){
- employeeRefs.remove(ref._key);
- }
- }
- public void clearCache(){
- cleanCache();
- employeeRefs.clear();
- System.gc();
- System.runFinalization();
- }
- }
Employee类:
- import java.lang.ref.Reference;
- import java.lang.ref.ReferenceQueue;
- import java.lang.ref.SoftReference;
- public class Employee {
- private String id;
- private String name;
- private String department;
- private String phone;
- private int salary;
- private String origin;
- public Employee(String id) {
- this.id = id;
- getDataFromInfoCenter();
- }
- private void getDataFromInfoCenter() {
- }
- public String getId() {
- String id = (int) (Math.random() * 10 + 1) + "";
- return id;
- }
- }
2、jdk中的引用实现类
代表软引用的类:java.lang.ref.SoftReference
代表弱引用的类:java.lang.ref.WeakReference
代表虚引用的类:java.lang.ref.PhantomReference
他们同时继承了:java.lang.ref.Reference
引用队列:java.lang.ref.ReferenceQueue,这个引用队列是可以三种引用类型联合使用的,以便跟踪java虚拟机回收所引用对象的活动。
附:相关源码
- /*
- * @(#)ReferenceQueue.java 1.23 03/12/19
- *
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
- * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
- */
- package java.lang.ref;
- /**
- * Reference queues, to which registered reference objects are appended by the
- * garbage collector after the appropriate reachability changes are detected.
- *
- * @version 1.23, 12/19/03
- * @author Mark Reinhold
- * @since 1.2
- */
- public class ReferenceQueue<T> {
- /**
- * Constructs a new reference-object queue.
- */
- public ReferenceQueue() { }
- private static class Null extends ReferenceQueue {
- boolean enqueue(Reference r) {
- return false;
- }
- }
- static ReferenceQueue NULL = new Null();
- static ReferenceQueue ENQUEUED = new Null();
- static private class Lock { };
- private Lock lock = new Lock();
- private Reference<? extends T> head = null;
- private long queueLength = 0;
- boolean enqueue(Reference<? extends T> r) { /* Called only by Reference class */
- synchronized (r) {
- if (r.queue == ENQUEUED) return false;
- synchronized (lock) {
- r.queue = ENQUEUED;
- r.next = (head == null) ? r : head;
- head = r;
- queueLength++;
- if (r instanceof FinalReference) {
- sun.misc.VM.addFinalRefCount(1);
- }
- lock.notifyAll();
- return true;
- }
- }
- }
- private Reference<? extends T> reallyPoll() { /* Must hold lock */
- if (head != null) {
- Reference<? extends T> r = head;
- head = (r.next == r) ? null : r.next;
- r.queue = NULL;
- r.next = r;
- queueLength--;
- if (r instanceof FinalReference) {
- sun.misc.VM.addFinalRefCount(-1);
- }
- return r;
- }
- return null;
- }
- /**
- * Polls this queue to see if a reference object is available. If one is
- * available without further delay then it is removed from the queue and
- * returned. Otherwise this method immediately returns <tt>null</tt>.
- *
- * @return A reference object, if one was immediately available,
- * otherwise <code>null</code>
- */
- public Reference<? extends T> poll() {
- synchronized (lock) {
- return reallyPoll();
- }
- }
- /**
- * Removes the next reference object in this queue, blocking until either
- * one becomes available or the given timeout period expires.
- *
- * <p> This method does not offer real-time guarantees: It schedules the
- * timeout as if by invoking the {@link Object#wait(long)} method.
- *
- * @param timeout If positive, block for up <code>timeout</code>
- * milliseconds while waiting for a reference to be
- * added to this queue. If zero, block indefinitely.
- *
- * @return A reference object, if one was available within the specified
- * timeout period, otherwise <code>null</code>
- *
- * @throws IllegalArgumentException
- * If the value of the timeout argument is negative
- *
- * @throws InterruptedException
- * If the timeout wait is interrupted
- */
- public Reference<? extends T> remove(long timeout)
- throws IllegalArgumentException, InterruptedException
- {
- if (timeout < 0) {
- throw new IllegalArgumentException("Negative timeout value");
- }
- synchronized (lock) {
- Reference<? extends T> r = reallyPoll();
- if (r != null) return r;
- for (;;) {
- lock.wait(timeout);
- r = reallyPoll();
- if (r != null) return r;
- if (timeout != 0) return null;
- }
- }
- }
- /**
- * Removes the next reference object in this queue, blocking until one
- * becomes available.
- *
- * @return A reference object, blocking until one becomes available
- * @throws InterruptedException If the wait is interrupted
- */
- public Reference<? extends T> remove() throws InterruptedException {
- return remove(0);
- }
- }
ReferenceQueue
- /*
- * @(#)SoftReference.java 1.34 03/12/19
- *
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
- * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
- */
- package java.lang.ref;
- /**
- * Soft reference objects, which are cleared at the discretion of the garbage
- * collector in response to memory demand. Soft references are most often used
- * to implement memory-sensitive caches.
- *
- * <p> Suppose that the garbage collector determines at a certain point in time
- * that an object is <a href="package-summary.html#reachability">softly
- * reachable</a>. At that time it may choose to clear atomically all soft
- * references to that object and all soft references to any other
- * softly-reachable objects from which that object is reachable through a chain
- * of strong references. At the same time or at some later time it will
- * enqueue those newly-cleared soft references that are registered with
- * reference queues.
- *
- * <p> All soft references to softly-reachable objects are guaranteed to have
- * been cleared before the virtual machine throws an
- * <code>OutOfMemoryError</code>. Otherwise no constraints are placed upon the
- * time at which a soft reference will be cleared or the order in which a set
- * of such references to different objects will be cleared. Virtual machine
- * implementations are, however, encouraged to bias against clearing
- * recently-created or recently-used soft references.
- *
- * <p> Direct instances of this class may be used to implement simple caches;
- * this class or derived subclasses may also be used in larger data structures
- * to implement more sophisticated caches. As long as the referent of a soft
- * reference is strongly reachable, that is, is actually in use, the soft
- * reference will not be cleared. Thus a sophisticated cache can, for example,
- * prevent its most recently used entries from being discarded by keeping
- * strong referents to those entries, leaving the remaining entries to be
- * discarded at the discretion of the garbage collector.
- *
- * @version 1.34, 12/19/03
- * @author Mark Reinhold
- * @since 1.2
- */
- public class SoftReference<T> extends Reference<T> {
- /* Timestamp clock, updated by the garbage collector
- */
- static private long clock;
- /* Timestamp updated by each invocation of the get method. The VM may use
- * this field when selecting soft references to be cleared, but it is not
- * required to do so.
- */
- private long timestamp;
- /**
- * Creates a new soft reference that refers to the given object. The new
- * reference is not registered with any queue.
- *
- * @param referent object the new soft reference will refer to
- */
- public SoftReference(T referent) {
- super(referent);
- this.timestamp = clock;
- }
- /**
- * Creates a new soft reference that refers to the given object and is
- * registered with the given queue.
- *
- * @param referent object the new soft reference will refer to
- * @param q the queue with which the reference is to be registered,
- * or <tt>null</tt> if registration is not required
- *
- */
- public SoftReference(T referent, ReferenceQueue<? super T> q) {
- super(referent, q);
- this.timestamp = clock;
- }
- /**
- * Returns this reference object's referent. If this reference object has
- * been cleared, either by the program or by the garbage collector, then
- * this method returns <code>null</code>.
- *
- * @return The object to which this reference refers, or
- * <code>null</code> if this reference object has been cleared
- */
- public T get() {
- T o = super.get();
- if (o != null) this.timestamp = clock;
- return o;
- }
- }
SoftReference
Java中四种引用:强、软、弱、虚引用的更多相关文章
- java中强,软,弱,虚引用 以及WeakHahMap
java中强,软,弱,虚引用 以及WeakHahMap 一:强软引用: 参考:http://zhangjunhd.blog.51cto.com/113473/53092/进行分析 packa ...
- java中的强,软,弱,虚引用
引用的应用场景 我们都知道垃圾回收器会回收符合回收条件的对象的内存,但并不是所有的程序员都知道回收条件取决于指向该对象的引用类型.这正是Java中弱引用和软引用的主要区别. 如果一个对象只有弱引用指向 ...
- java中四种引用类型(对象的强、软、弱和虚引用)
对象的强.软.弱和虚引用在JDK 1.2以前的版本中,若一个对象不被任何变量引用,那么程序就无法再使用这个对象.也就是说,只有对象处于可触及(reachable)状态,程序才能使用它.从JDK 1.2 ...
- java中四种引用类型
java中四种引用类型 今天看代码,里面有一个类java.lang.ref.SoftReference把小弟弄神了,试想一下,接触java已经有3年了哇,连lang包下面的类都不了解,怎么混.后来在 ...
- Java中四种引用的区分
强引用(StrongReference) 强引用就是指在程序代码之中普遍存在的,比如下面这段代码中的object和str都是强引用: 1 2 Object object = new Object(); ...
- java中四种引用类型(转)
今天看代码,里面有一个类java.lang.ref.SoftReference把小弟弄神了,试想一下,接触java已经有3年了哇,连lang包下面的类都不了解,怎么混.后来在网上查资料,感觉收获颇多, ...
- Java中四种访问权限总结
一.Java中有四种访问权限, 其中三种有访问权限修饰符,分别为private.public.protected,还有一种不带任何修饰符(default). 1. private: Java语言中对访 ...
- java中四种操作(dom、sax、jdom、dom4j)xml方式详解与比较
1)DOM(JAXP Crimson解析器) DOM是用与平台和语言无关的方式表示XML文档的官方W3C标准.DOM是以层次结构组织的节点或信息片断的集合.这个层次结构允许开发人员在树中寻找特 ...
- java中四种操作xml方式的比较
1)DOM(JAXP Crimson解析器) DOM是用与平台和语言无关的方式表示XML文档的官方W3C标准.DOM是以层次结构组织的节点或信息片断的集合.这个层次结构允许开发人员在树中寻找特定信息. ...
随机推荐
- gdb汇编调试
GDB调试汇编堆栈分析 代码: sudo apt-get install libc6-dev-i386命令安装所需库 进入之后先在main函数处设置一个断点,再run一下,使用disassemble指 ...
- java使用jsch连接linux
由于项目需要使用java来linux进行管理,近一番查找,发现第三方jar包 jsch 可以轻松实现对linux的管理,(相关文档及例子请访问官网www.jcraft.com),故引进. 在网上搜索了 ...
- Appium UI自动化的那些梗
@作者 彭海波 转载请注明出处 前言 由于需求的快速迭代和敏捷测试的要求,在测试过程中引入自动化成为必不可少的手段.作为一个互联网测试团队,我们自然也引入了自动化测试这个环节.在众多的测试框架中,我们 ...
- xhprof学习笔记
一.简介 XHProf 是一个轻量级的分层性能测量分析器. 在数据收集阶段,它跟踪调用次数与测量数据,展示程序动态调用的弧线图. 它在报告.后期处理阶段计算了独占的性能度量,例如运行经过的时间.CPU ...
- jfinal相关
1:jfinal工具类 1):密码加密工具 HashKit.md5(String password);2):数据缓存工具类 chacheKit3):获取项目路径工具类: PathKit 4):读取文件 ...
- 配合crond服务实现自定义周期备份MySQL数据库(使用innobackupex进行备份)
备份 新建一个脚本/root/backup.py,内容如下: #!/usr/bin/env python# -*- coding: utf-8 -*- ''' 脚本作者:昨夜星辰 脚本作用:配合cro ...
- asp.net core获取自定义json的配置内容
首先在主目录下建立:Iyibank.Web.json文件 里边的内容如下: { "ConnectionStrings": { "RedisCache": &qu ...
- 6.openssl rsautl和openssl pkeyutl
rsautl是rsa的工具,相当于rsa.dgst的部分功能集合.可用于签名.验证.加密和解密文件.非对称密钥的密钥是随机生成的,因此不需要也无法指定salt参与加密. pkeyutl是非对称加密的通 ...
- I2C总线和S5PV210的I2C总线控制器
一.什么是I2C通信协议? 1.物理接口:SCL + SDA (1)SCL(serial clock):时钟线,传输CLK信号,一般是I2C主设备向从设备提供时钟的通道. (2)SDA(serial ...
- python之路-Day8
抽象接口 class Alert(object): '''报警基类''' def send(self): raise NotImplementedError class MailAlert(Alert ...