Java的内存与回收

来源:互联网 发布:软件测试学校 编辑:程序博客网 时间:2024/05/22 15:34

Java引用的种类

1.对象在内存中的状态

对于JVM的垃圾回收机制来说,是否回收一个对象的标准在于:是否还有引用变量引用改对象?只要有引用变量引用对象,垃圾回收机制就不会回收它。

也就是说,当java对象被创建出来之后,垃圾回收机制会实时的监控每个对象的运行状态,包括对象的申请,引用,被引用,赋值等。当垃圾回收机制实时的监控到某个对象不再被引用变量所引用时,垃圾回收机制就会回收它所占用的空间。

基本上,可以把JVM内存中的对象引用理解成一种有向图,把引用变量,对象都当成有向图的顶点,将引用关系当成图的有向边,有向边总是从引用端指向被引用的Java对象。因为Java的所有对象都是由一条条线程创建出来的,因此可以把线程对象当成有向图的起始顶点。

对于单线程程序而言,整个程序只有一条main线程,那么该图就是以main进程为顶点的有向图。在这个有向图中,main顶点可达的对象都处于可达状态,垃圾回收机制不会回收它们;如果某个对象在这个有向图中处于不可达状态,那么就认为这个对象不再被引用。

采用有向图管理内存中的对象具有较高的精度,当缺点是效率较低。

当一个对象在堆内存中运行时,根据它在对应有向图中的状态,可以把它所处的状态分成

  • 可达状态:当一个对象被创建后,有一个以上的引用变量引用它。在有向图中可以从起始顶点导航到该对象,那么它就处于可达状态,程序可以通过引用变量来调用该对

    象的属性和方法。

  • 可恢复状态:如果程序中某个对象不再有任何引用变量引用它,它将先进入可恢复状态,此时从有向图的起始顶点不能导航到该对象。在这种状态下,系统的垃圾回

    收机制准备回收该对象所占用的内存。在回收该对象之前,系统会调用可恢复状态的对象的finalize方法进行资源清理,如果系统调用finalize方法重新让一个以L的

    引用变量引用该对象,则这个对象会再次变为可达状态:否则,该对象将进入不可达状态。

  • 不可达状态:书对象的所有关联都被切断,fl甲系统调用所有对象的finaii}e方法依然没有使该对象变成可达状态后,这个对象将永久性地失去引用,最后变成不可达状态。只有当一个对象处于不可达状态时,系统才会真正回收该对象所占有的资源。

memery.PNG

一个对象可以被一个方法的局部变量引用,也可以被其他类的类变量引用,或者被其他对象的实例变量引用。当某个对象被其他类的类变量引用时,只有该类被销毁后,该对象才会进入可恢复状态;当某个对象那个被其他对象的实例变量引用时,只有当引用该对象的对象被销毁或变成不可达状态后,改对象才会进入不可达状态。

对于垃圾回收机制来说,判断一个对象是否可回收的标准就在改对象是否被引用,因此引用也是JVM进行内存管理的一个重要概念。为了更好的管理对象的引用,从JDK1.2开始,Java在java.lang.ref包下提供了三个类:SoftReference,PhantomReference和WeakReference,它们分别代表了系统对对象的三种引用方式:软引用,虚引用和弱引用。归纳起来,Java语言对对象的引用有如下四种:

  • 强引用

  • 软引用

  • 弱引用

  • 虚引用

强引用

当程序创建一个对象,并把这个对象赋给一个引用变量,这个引用变量就是强引用。强引用是最常见的。

当一个对象被一个或一个以上的强引用变量所引用时,它处于可达状态,它不可能被系统垃圾回收机制回收,即使系统内存非常紧张,即使有些Java对象以后永远都不会被用到,JVM也不会回收被强引用所引用的Java对象。

由于JVM肯定不会回收被强引用所引用的Java对象,因此强引用时造成Java内存泄漏的只要原因之一。

.软引用

对于强引用所引用的Java对象而言,无论系统的内存如何紧张,即使某些Java以后不再使用,垃圾回收机制也不会回收它所占的内存。但软引用不同,当系统内存充足时,和强引用是没有什么区别的。但是当系统内存不足时,软引用所引用的Java对象可以被垃圾回收机制回收,从而避免系统内存的不足的异常。

当程序需要大量创建某个类的新对象,而且有可能重新访问已创建的来对象是,可以充分使用软引用来解决内存紧张的难题。

弱引用

弱引用与软引用有点相似,区别在于弱引用所引用的对象的生命周期更短。弱引用通过WeakReference类实现。对于软引用的对象而言,当系统垃圾回收机制运行时,不管系统内存时候足够,总会回收改对象所占用的内存。当然,并不是说当一个对象只有弱引用时,它就会立即被回收,正如那些失去引用的对象一样,必须等到系统垃圾回收机制运行时才会被回收。

弱引用具有很大的不确定性,因为每次垃圾回收机制执行时都会回收弱引用所引用的对象,而垃圾回收机制的运行又不受程序员的控制,因此程序获取弱引用所引用的Java对象是必须小心空指针异常,通过弱引用所获取的Java对象可能是null.

虚引用

弱引用和软引用可以单独使用,当虚引用不能单独使用,单独使用虚引用没有太大的意义。虚引用的主要作用就是跟踪对象被垃圾回收的状态,程序可以通过检查与虚引用关联的引用队列中是否包含指定的虚引用,从而了解虚引用所引用的对象是否即将被回收。虚引用通过PhantomReference类实现,他完全类似于没有引用。虚引用对对象本身没有太大的影响,对象甚至感觉不到虚引用的存在。