Java垃圾回收机制

时间:2020-12-10 00:02:24

程序员都了解初始化的重要性,但常常会忘记同样也重要的清理工作,这篇介绍下Java中垃圾回收机制和其中finalize()方法的用途何在?

垃圾回收

 垃圾回收是Java中自动内存管理的另一种叫法。垃圾回收的目的是为程序保持尽可能多的可用堆(heap)。 JVM会删除堆上不再需要从堆引用的对象。

 Java的垃圾回收是由JVM自动进行,对于程序员是不可控的。
 System.gc(); Sysytem.getRuntime().gc();调用这两个方法并不会立即进行垃圾回收。

 

Java 语言将内存分配和释放的工组交给了自己,程序员不必做这些工作,它提供一个系统级的线程跟踪每个内存的分配,在 JVM 的空闲处理中,垃圾收集线程将检查和释放不再使用的内 存(即可以被释放的内存)。垃圾收集的过程在 Java 程序的生存期中是自动的,不需要分配和释放内存, 也避免了内存泄漏。可以调用 System.gc()方法建议 JVM 执行垃圾收集以使得可被释放的内存能立即被 使用,当此方法返回的时候,JVM 已经做了最大的努力从被丢弃的对象上回收内存空间。程序员不能指 定收集哪些内存,一般而言也不用关心这个问题,除非是程序的内存消耗很大,特别是有很多临时对象 时可以“建议“进行垃圾收集以提高可用内存。需要指出的是调用 System.gc()方法不能保证 JVM 立即 进行垃圾收集,而只能是建议,因为垃圾收集线程的优先级很低(通常是最低的)。JVM 垃圾收集器收集一个对象之前,一般要求程序调用适当的方法释放资源,但在没有明确释放资 源的情况下,Java 提供了缺省机制来终止化该对象心释放资源,这个方法就是 finalize( )。

 

什么时候运行垃圾回收?

运行垃圾收集的可能情况是:

1.堆可用内存不足
2.CPU空闲

垃圾回收的最佳做法?

用编程的方式,我们可以手动让JVM通过调用System.gc()方法来运行垃圾回收。

当内存已满,且堆上没有对象可用于垃圾回收时,JVM可能会抛出OutOfMemoryException。

对象在被垃圾回收从堆上删除之前,会运行finalize()方法。我们建议不要用finalize()方法写任何代码。

为什么Gc回收不了流对象?

Gc是主要清理内存,但close方法还要释放掉一些系统资源,比如硬盘读写所使用的资源。

另外,不close,那么程序还是在运行,没有结束,所以gc不把它当成垃圾,回收不了。

如果一个流不关闭会产生一些额外问题,比如说锁定了某种资源,如果你用流打开了一个文件,没有关闭的话,

这个文件就删不掉,会提示有程序在操作这个文件,而且也会占用系统句柄。

finalize()方法的用途何在?

Java垃圾 回收器只知道释放那些经new分配的内存,所以它不知道该如何释放该对象的这块"特殊"内存,为了应对这种情况,Java允许在类中定义一个名为finalize()的方法

,它的工作原理是这样的:

一旦垃圾回收器准备好释放对象占用的存储空间,将首先调用finalize()方法,并且在下一次垃圾回收动作发生时,才会真正回收对象占用的内存。所以要是你打算用finalize(),就能

在垃圾回收时刻做一些重要的清理工作。

小结:

1.对象可能不被垃圾回收。

2.垃圾回收并不等于"析构"(正因为垃圾回收机制的存在,所以不存在析构)。

3.垃圾回收只与内存有关。

也就是说,使用垃圾回收器的唯一原因是为了回收程序不再使用的内存,所以对于垃圾回收相关的任何行为来说(尤其是finalize()方法),他们也必须同内存及其回收有关,

但是这是否意味着要是对象中含有其他对象,finalize()就应该明确释放那些对象呢?不,无论对象时如何创建的,垃圾回收器都会负责释放对象占据的所有内存,这就将对finalize()的需求

限制到一种特殊情况,即通过某种创建对象方式以外的方式为对象分配了存储空间。

4.也许你会发现,只要程序没有濒临存储空间用完的那一刻,对象占用的空间总也得不到释放,如果程序执行结束,并且垃圾回收器一直都没有释放你创建的任何对象的存储空间,则随着程序的

退出,那些资源也会全部交给操作系统,这个策略是恰当的,因为垃圾回收本身也有开销,要是不使用它那就不用支付这部分开销了。