垃圾回收

来源:互联网 发布:matlab从文件读取数据 编辑:程序博客网 时间:2024/05/11 14:54

                             垃圾回收

JAVA的对内存是一个运行时数据区,用以保存类的实例(对象),JAVA虚拟机的内存中存储着正在运行的应用程序建立所建立的所有对象,这些对象不需要程序通过代码来显示释放。一般来说,堆内存的回收由垃圾回收来负责,所有JVM实现都有一个由垃圾回收器管理的堆内存。垃圾回收是一种动态存储管理技术,它自动释放不再被程序引用的对象,按照特定的垃圾回收算法来实现内存资源的自动回收功能。

    

说到垃圾回收(Garbage Collection,GC),很多人就会自然而然地把它和Java联系起来。在Java中,程序员不需要去关心内存动态分配和垃圾回收的问题,这一切都交给了JVM来处理。顾名思义,垃圾回收就是释放垃圾占用的空间,那么在Java中,什么样的对象会被认定为垃圾那么当一些对象被确定为垃圾之后,采用什么样的策略来进行回收(释放空间)?在目前的商业虚拟机中,有哪些典型的垃圾收集器?

垃圾回收机制

一. 垃圾回收的特点:

1.      垃圾回收机制的工作目标是回收无用对象的内存空间,这些内存空间是JVM堆内存的内存空间,垃圾回收只能回收内存资源,对于其他的物理资源如:数据库连接,硬盘I/O等资源则是无效的。

2.      为了让垃圾回收机制回收那些不再使用的对象,可以将引用变量设置为null,通过这种方式告诉垃圾回收机制可以回收该对象。

3.      垃圾回收发生的不可预知性。不同的JVM采用了不同的垃圾回收机制和不同的垃圾算法,因此它可能是定时发生,也有可能当CPU空闲时发生,也有可能和原始的垃圾回收机制相同,当内存出现极限时发生,我们可以通过调用Runtime对象的gc()和System.gc()

建议系统进行垃圾回收,这种方式依然不能精确的控制垃圾回收机制的执行。

4.      准确性主要包括两个方面:一是垃圾回收机制能够精确的标记活着的对象;二是垃圾回收器能够精确的定位对象之间的引用关系。前者是完全回收所有废弃对象的前提,否则就可能出现内存的泄露;后者实现归并和复制的必要条件,通过这种方法可以保证所有对象都被可靠的回收,所有对象都能背后从新分配,从而减少内存碎片的产生。

5.      现在JVM有多种的不同垃圾回收实现。

 

二.如何确定某个对象是“圾”?

一.GC执行条件

JVM进行次GC的频率很高,但因为这种GC占用时间极短,所以对系统产生的影响不大。更值得关注的是主GC的触发条件,因为它对系统影响很明显。总的来说,有两个条件会触发GC

   1.当没有引用变量指向原先分配给某个对象的内存时,该内存便成为垃圾,JVM的一个超级线程会自动释放该内存区。垃圾回收意味着程序不再需要的对象是“垃圾信息”,这个信息将被丢弃。

       2.Java堆内存不足时,GC会被调用。当应用线程在运行,并在运行过程中创建新对象,若这时内存空间不足,JVM就会强制地调用GC线程,以便回收内存用于新的分配。若GC一次之后仍不能满足内存分配的要求,JVM会再进行两次GC作进一步的尝试,若仍无法满足要求,则 JVM将报“out of memory”的错误,Java应用将停止。

强制系统垃圾回收的两种方式:

1.      调用System类的gc()静态方法:System.gc().

2.      调用Runtime对象的gc()实例方法:Runtime.getRuntime().gc()。

Finaliza()方法具有如下4种特点。

1.      永远不会主动调用某个对象的finalize()方法,该方法应交给垃圾回收机制调用。

2.      Finalize()方法何时被调用,是否被调用具有不确定性,不要把finalize()方法当成一定会被执行的方法。

3.      当JVM执行可恢复对象的finalize()方法时,可能使该对象或系统中其他对象重新回到可达状态。

4.      当JVM执行finalize()方法出现异常时,垃圾回收机制不会报告异常,程序继续执行。

 

 

 

二.Java 中有不同的引用类型。判断实例是否符合垃圾收集的条件都依赖于它的引用类型。

 

引用类型

垃圾收集

强引用(Strong Reference

不符合垃圾收集

软引用(Soft Reference

垃圾收集可能会执行,但会作为最后的选择

弱引用(Weak Reference

符合垃圾收集

虚引用(Phantom Reference

符合垃圾收集

强引用:这是java程序中最常见的应用类型。程序创建一个对象,并把这个对象赋给一个引用变量,程序通过该引用变量来操作实际的对象,当一个对象被一个或多个的引用变量所引用时,它处于可达状态,不可能被系统垃圾回收机制回收。

软引用:

 

 

 

 

三.典型的垃圾收集算法

一.引用技术算法

       在java中是通过引用来和对象进行关联的,也就是说如果要操作对象,必须通过引用来进行。那么很显然一个简单的办法就是通过引用计数来判断一个对象是否可以被回收。不失一般性,如果一个对象没有任何引用与之关联,则说明该对象基本不太可能在其他地方被使用到,那么这个对象就成为可被回收的对象了。这种方式成为引用计数法。

这种方式的特点是实现简单,而且效率较高,但是它无法解决循环引用的问题,因此在Java中并没有采用这种方式(Python采用的是引用计数法)。看下面这段代码:

 


 

最后面两句将object1和object2赋值为null,也就是说object1和object2指向的对象已经不可能再被访问,但是由于它们互相引用对方,导致它们的引用计数都不为0,那么垃圾收集器就永远不会回收它们。

二.可达性分析算法

这个算法的基本思路就是通过一系列的称谓“GC Roots"的对象作为起始点,从这些节点开始向下搜索,搜索所有走过的路径为引用链,当一个对象到GC Roots没有任何引用链项链时,则证明此对象时不可用的

 

上面的这张图,对象object5、object6、object7虽然互相没有关联,但是它们到GC Roots是不可达的,所以它们将会被判定为是可回收的对象

 

四.典型的垃圾收集器

1.每一个对象都有一个finalize方法,这个方法是从Object类继承来的。

2.每一个对象只能调用finalize方法一次。如果在finalize方法执行时产生异常(exception),则该对象仁可以被垃圾回收集器收集。

3.finalize方法可以被重载,但是又具备初始的finalize方法特点的。

4.finalize方法可以明确地被调用,但它却不能进行垃圾收集

5.垃圾收集不可以被强制执行,但程序员可以通过调用System.gc方法来建仪执行垃圾收集器

 

原创粉丝点击