Java中的引用类型和垃圾回收

Wesley13
• 阅读 693

强引用Strong References
  强引用是最常见的引用:

  比如:

StringBuffer buffer = new StringBuffer();
  创建了一个StringBuffer类的对象,并用一个变量buffer存储对这个对象的引用。这就是个强引用。

  变量持有的是这个对象的引用。通常,引用是一个对象的存储地址。

  Java不像C或者C++一样,Java没有取地址符号&,也没有解引用符号*或者->。

  引用不同于指针,引用不能与整形进行互相转换,也不能进行增减操作。

  强引用是和垃圾回收机制相关的。

  一般的,如果一个对象可以通过一系列的强引用引用到,那么就说明它是不会被垃圾回收机制(Garbage Collection)回收的。

  因为垃圾回收是不会回收你正在使用的对象的。

垃圾回收机制Garbage Collection
  如果一个对象,没有一个引用指向它,那么它就被认为是一个垃圾。

  An object is considered garbage when there are no longer any references to it stored in any variables, the fields of any objects, or the elements of any arrays.

  在某一个时间,garbage collector将会发现成为垃圾的对象,然后回收它所占用的内存。

  C中用malloc()和free()来管理内存。

  C++是用new和delete来分配和管理内存空间。

  而Java使用garbage collection机制,不用程序员写代码管理,这样会有一些性能上的影响,因为garbage collector会主动地回收内存。

  但是,GC机制减少了内存泄露,并且提高了程序员的效率。

什么时候强引用会太强了?
  有时候应用会使用一些不能被继承的类,比如一个final的类,或者一个工厂方法返回的接口,并不知道有多少具体实现。

  而我们想给这个类增加一个字段,比如给每一个对象一个序列号,于是我们用了HashMap,把这个类的对象作为key,一个序列号作为value。

  这时候我们就必须100%确定地知道一个特定对象的序列号什么时候不再需要(比如对象的生命周期已经结束,就不再需要它的序列号属性),这样我们就可以从map中移除它的entry。

  如果我们在应当移除引用的时候没有移除,垃圾回收将一直不会回收这个对象,引起内存泄露。

  而如果我们过早地移除了我们还在使用的对象的引用,又会发现自己丢失了信息。

  这些都是C/C++程序员经常会遇到的问题。而我们用的是Java,我们还要考虑这些,岂不是闹复杂了?

  强引用另一个常见的问题是缓存问题。

  比方说,图像的缓存。图像缓存应当阻止我们重复载入图像。

  所以图像缓存保存有内存中已有的所有图像的引用,如果使用通常的强引用,强引用本身会使得图像一直存留在内存中,这样就使得程序员像上面一样,必须自己决定什么时候移除缓存中的引用,这样对象才能被垃圾回收机制回收。

  这样你就又放弃了让GC自己管理垃圾回收的机制,而开始手动地管理内存。

引用对象类
  Java的引用对象类在包java.lang.ref下。

  http://docs.oracle.com/javase/7/docs/api/java/lang/ref/package-summary.html#package_description

  其中包含了三种显式的引用类型(也即是Reference类的三个子类):

  SoftReference

  WeakReference

  PhantomReference

  一个引用对象(reference object)(即以上三种引用类型的对象)封装了一个对其他对象的引用(称作referent)。

  引用对象提供了对referent的clean和get操作,但是不提供set操作。

  引用对象本身可以像其他一般的对象一样被检查和操纵。

  三种类型的引用定义了三种不同层次的可达性级别,由强到弱排列如下:

  SoftReference > WeakReference > PhantomReference

  越弱表示对垃圾回收器的限制越少,对象越容易被回收。

SoftReference
  SoftReference用来实现一些内存敏感的缓存(Soft references are for implementing memory-sensitive caches),只要内存空间足够,对象就会保持不被回收。

  反之,当宿主进程的内存空间不足时,对象就会被GC回收。

  所以SoftReference意味着:hold on until you can’t.

WeakReference
  WeakReference可以用来实现一些规范化映射(WeakHashMap),其中key或者value当它们不再被引用时可以自动被回收。

  当你想引用一个对象,但是这个对象有自己的生命周期,你不想介入这个对象的生命周期,这时候你就是用弱引用。

  这个引用不会在对象的垃圾回收判断中产生任何附加的影响。

PlantomReference
  PlantomReference和WeakReference一样,也不会介入引用对象的生命周期。

  PhantomReference用来调度一些预验清理动作,提供比Java清理机制更灵活的处理方式。(Phantom references are for scheduling pre-mortem cleanup actions in a more flexible way than is possible with the Java finalization mechanism.)

  PlantomReference比较特殊,它的get方法总是返回null,所以你得不到它引用的对象。

  它保存ReferenceQueue中的轨迹。

  它允许你知道对象何时从内存中移除。

点赞
收藏
评论区
推荐文章
Wesley13 Wesley13
3年前
java 复制Map对象(深拷贝与浅拷贝)
java复制Map对象(深拷贝与浅拷贝)CreationTime2018年6月4日10点00分Author:Marydon1.深拷贝与浅拷贝  浅拷贝:只复制对象的引用,两个引用仍然指向同一个对象
待兔 待兔
3个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Wesley13 Wesley13
3年前
java 强引用,软引用,弱引用,虚引用
强引用(StrongReference)强引用是使用最普遍的引用。如果一个对象具有强引用,那垃圾回收器绝不会回收它。当内存空间不足,Java虚拟机宁愿抛出OutOfMemoryError错误,使程序异常终止,也不会靠随意回收具有强引用的对象来解决内存不足的问题。我们平常使用的大多数是强引用。软引用(SoftReference)如果
九路 九路
3年前
2 Java对象的创建过程
JAVA中创建对象直接new创建一个对象,对么对象的创建过程是怎样的呢?程序运行过程中有许多的对象被创建出来.那么对象是如何创建的呢?一对象创建的步骤1遇到new指令时,检查这个指令的参数是否能在常量池中找到一个符号引用2如果找到符号引用,就检查这个符号引用是否已经被加载,解析和初始化过3如果没有加载过,则执行类加载过程
Wesley13 Wesley13
3年前
Java对象的引用类型
!(https://oscimg.oschina.net/oscnet/24d3ddce8c92eb32f8e3a68063234324da7.jpg)     Java对象的引用类型有强引用,软引用,弱引用,虚引用和FinalReference,提供这几种引用类型的主要目的:1.程序员可以通过不同的引用方式决定某些对象的生命周期;2.
Stella981 Stella981
3年前
JVM调优总结一
数据类型   Java虚拟机中,数据类型可以分为两类:基本类型和引用类型。基本类型的变量保存原始值,即:他代表的值就是数值本身;而引用类型的变量保存引用值。“引用值”代表了某个对象的引用,而不是对象本身,对象本身存放在这个引用值所表示的地址的位置。基本类型包括:byte,short,int,long,cha
Wesley13 Wesley13
3年前
Java虚拟机篇(面试)
!面试重点:Java虚拟机篇(http://p3.pstatp.com/large/5e84000330ca26c3c6c6)一、Java引用的四种状态:强引用:  用的最广。我们平时写代码时,new一个Object存放在堆内存,然后用一个引用指向它,这就是强引用。  如果一个对象具有强引用,那垃圾回
Stella981 Stella981
3年前
JVM笔记整理
不对之处还望指正。垃圾回收1\.如何判断对象是垃圾对象?引用计数法在对象中添加一个引用计数器,当有地方引用这个对象的时候,引用计数器的值1,当引用失效时,则值1.此方式不能解决循环引用的问题。验证添加gc日志,\_005GC.javaverbose:gc
Wesley13 Wesley13
3年前
PHP垃圾回收机制
php5.3之前使用的垃圾回收机制是单纯的“引用计数”,也就是每个内存对象都分配一个计数器,当内存对象被变量引用时,计数器1;当变量引用撤掉后,计数器1;当计数器0时,表明内存对象没有被使用,该内存对象则进行销毁,垃圾回收完成。“引用计数”存在问题,就是当两个或多个对象互相引用形成环状后,内存对象的计数器则不会消减为0;这时候,这一组内存对象已经
Stella981 Stella981
3年前
JVM调优总结(一)基本概念
数据类型Java虚拟机中,数据类型可以分为两类:基本类型和引用类型。    基本类型:保存原始值,即:他代表的值就是数值本身;    引用类型:保存引用值。“引用值”代表了某个对象的引用,而不是对象本身,对象本身存放在这个引