简单谈谈Java垃圾回收

时间:2021-10-23 05:08:06

好久没看关于java的书了,最近,看了James Gosling的<<Java程序设计语言>>,做了一些读书笔记。这部分是关于垃圾回收的。

一. 垃圾回收

对象是使用new创建的,但是并没有与之相对应的delete操作来回收对象占用的内存。当我们完成对某个对象的使用时,只需停止该对象的引用:

->将引用改变为指向其他对象
->将引用指向null
->从方法中返回, 使得该方法的局部变量不复存在

要点:

->当我们从任何可执行代码都无法到达某个对象时,它所占用的空间就可以被回收。
->垃圾回收意味着我们永远不用担心出现虚悬引用(dangling reference)。虚悬引用,指得是引用已经被删除的内存空间。在那些程序员可以直接控制何时删除对象的系统中,会存在这样的问题。
->垃圾回收器模型:引用计数器法(不能解决循环引用),标记-清除(mark-and-sweep)。

二. 总结

finalize方法

->在垃圾回收器确定该对象是不可达的且该对象的空间将被回收之后,垃圾回收器就会调用这个方法。
->这个方法可以清除该对象所使用的所有非内存资源,对每一个对象最多只能调用一次,即使在这个方法的执行使得该对象重新变为可达之后又马上会再次变为不可达的情况下,该方法也只能调用一次。
->finalize方法可以在任何特定的时间段内被调用,它也可能永远不会被调用(java虚拟机结束)。

覆写finalize方法

->当一个对象变成垃圾时,它所引用的其他对象也很有可能会变成垃圾。这些垃圾可能在调用我们编写的finalize方法之前就已经被终结了,因此它们可能处于不可预知的状态。
->覆写finalize方法是,加上super.finalize方法。最好加在finally字句里面。保证其超类中声明的部分内容也可以被终结。

三. 与垃圾回收器交互的相关类和方法

类:Runtime.getRuntime(), System
方法:gc(), runFinalization(), freeMemory(), totalMemory(), maxMemory()
System类支持静态的gc()和runFinalization()方法,它们将调用当前Runtime对象上的相应方法。

四. 可达性状态和引用对象

对象只有在没有任何引用指定它的时候才可以被当作垃圾回收,但有时我们可能希望在仍旧有选定引用指向对象时,将该对象作为垃圾回收掉。

引用对象的唯一用途就是维护对另一个被称为指称物(referent)的对象的引用。通常我们通过字段或者局部变量来维护对对象的引用,但是现在我们可以维护对引用对象的直接引用,而该引用对象包装了我们实际需要的对象。垃圾回收器可能判断出对某个对象的残留引用是否都是经由引用对象面引用到该对象的,因此它可以决定是否要回收该对象。引用对象的强度将决定垃圾回收器的行为,普通的引用都是强度最大的引用。

Reference类

->包:java.lang.ref
->典型方法: get(), clear(), enqueue(), isEnqueued()

引用和可达性强度

->对象是强可达的(strongly reachable):普通的引用
->对象是软可达的(softly reachable):SoftReference
->对象是弱可达的(weakly reachable):WeakReference
->对象是虚可达的(phantom reachable):PhantomReference
->对象是不可达的:没有引用链接
一旦对象变为弱可达的(或者列弱),它就可以被终结。如果在终结之后该对象是不可达的,那么它就可以被回收了。

对象可达性阶段会触发垃圾回收器对相关的引用对象类型做出适当的行为:

->软可达对象可能会任凭垃圾回收器去回收。我们可确定的是所有对软可达对象的SoftReference都会在抛出outofMemoryError错误这前被清除。
->弱可达对象将会被垃圾回收器回收。
->虚可达对象并不是真正意义上的可达,因为无法通过PhantomReference访问其指称对象,其get方法总是返回null。但是虚引用的存在可以防止对象在显式清除虚引用之前被回收。虚引用使我们可以处理那些finalize方法已经被调用过的对象,从而可以安全地认为它们是"死"的。