java垃圾处理

版权声明: https://blog.csdn.net/weixin_39892293/article/details/79666372


1.垃圾回收


对象是使用new创建的, 但是并没有与之相对应的delete操作来回收对象占用的内存. 当我们完成对某个对象的使用时, 只需停止该对象的引用:
->将引用改变为指向其他对象
->将引用指向null
->从方法中返回, 使得该方法的局部变量不复存在


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


2.终结


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


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


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


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


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


引用对象的唯一用途就是维护对另一个被称为指称物(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方法已经被调用过的对象, 从而可以安全地认为它们是"死"的.




写程序时候的准则:
(1)不要试图去假定垃圾收集发生的时间,这一切都是未知的。
比如,方法中的一个临时对象在方法调用完毕后就变成了无用对象,这个时候它的内存就可以被释放。 


(2)Java中提供了一些和垃圾收集打交道的类,
而且提供了一种强行执行垃圾收集的方法--调用System.gc(),
但这同样是个不确定的方法。Java 中并不保证每次调用该方法就一定能够启动垃圾收集,
它只不过会向JVM发出这样一个申请,到底是否真正执行垃圾收集,一切都是个未知数。


(3)挑选适合自己的垃圾收集器。一般来说,如果系统没有特殊和苛刻的性能要求,
可以采用JVM的缺省选项。否则可以考虑使用有针对性的垃圾收集器,
比如增量收集器就比较适合实时性要求较高的系统之中。
系统具有较高的配置,有比较多的闲置资源,可以考虑使用并行标记/清除收集器。


(4)关键的也是难把握的问题是内存泄漏。
良好的编程习惯和严谨的编程态度永远是最重要的,不要让自己的一个小错误导致内存出现大漏洞。


(5)尽早释放无用对象的引用。
大多数程序员在使用临时变量的时候,
都是让引用变量在退出活动域(scope)后,自动设置为null,
暗示垃圾收集器来收集该对象,还必须注意该引用的对象是否被监听,如果有,则要去掉监听器,然后再赋空值。


就是说,对于频繁申请内存和释放内存的操作,还是自己控制一下比较好,
但是System.gc()的方法不一定适用,最好使用finallize强制执行或者写自己的finallize方法。

猜你喜欢

转载自blog.csdn.net/weixin_39892293/article/details/79666372