Android内存优化4 了解java GC 垃圾回收机制2 GC执行finalize的过程
1. finalize的作用
- finalize()是Object的protected方法,子类可以覆盖该方法以实现资源清理工作,GC在回收对象之前调用该方法。
- finalize()与C++中的析构函数不是对应的。C++中的析构函数调用的时机是确定的(对象离开作用域或delete掉),但Java中的finalize的调用具有不确定性
- 不建议用finalize方法完成“非内存资源”的清理工作,但建议用于:① 清理本地对象(通过JNI创建的对象);② 作为确保某些非内存资源(如Socket、文件等)释放的一个补充:在finalize方法中显式调用其他资源释放方法。其原因可见下文[finalize的问题]
2. finalize的问题
- 一些与finalize相关的方法,由于一些致命的缺陷,已经被废弃了,如System.runFinalizersOnExit()方法、Runtime.runFinalizersOnExit()方法
- System.gc()与System.runFinalization()方法增加了finalize方法执行的机会,但不可盲目依赖它们
- Java语言规范并不保证finalize方法会被及时地执行、而且根本不会保证它们会被执行
- finalize方法可能会带来性能问题。因为JVM通常在单独的低优先级线程中完成finalize的执行
- 对象再生问题:finalize方法中,可将待回收对象赋值给GC Roots可达的对象引用,从而达到对象再生的目的
- finalize方法至多由GC执行一次(用户当然可以手动调用对象的finalize方法,但并不影响GC对finalize的行为)
3. finalize的执行过程(生命周期)
- unfinalized: 新建对象会先进入此状态,GC并未准备执行其finalize方法,因为该对象是可达的
- finalizable: 表示GC可对该对象执行finalize方法,GC已检测到该对象不可达。正如前面所述,GC通过F-Queue队列和一专用线程完成finalize的执行
- finalized: 表示GC已经对该对象执行过finalize方法
- reachable: 表示GC Roots引用可达
- finalizer-reachable(f-reachable):表示不是reachable,但可通过某个finalizable对象可达
- unreachable:对象不可通过上面两种途径可达
- 新建对象首先处于[reachable, unfinalized]状态(A)
- 随着程序的运行,一些引用关系会消失,导致状态变迁,从reachable状态变迁到f-reachable(B, C, D)或unreachable(E, F)状态
- 若JVM检测到处于unfinalized状态的对象变成f-reachable或unreachable,JVM会将其标记为finalizable状态(G,H)。若对象原处于[unreachable,
unfinalized]状态,则同时将其标记为f-reachable(H)。 - 在某个时刻,JVM取出某个finalizable对象,将其标记为finalized并在某个线程中执行其finalize方法。由于是在活动线程中引用了该对象,该对象将变迁到(reachable,
finalized)状态(K或J)。该动作将影响某些其他对象从f-reachable状态重新回到reachable状态(L, M, N) - 处于finalizable状态的对象不能同时是unreahable的,由第4点可知,将对象finalizable对象标记为finalized时会由某个线程执行该对象的finalize方法,致使其变成reachable。这也是图中只有八个状态点的原因
- 程序员手动调用finalize方法并不会影响到上述内部标记的变化,因此JVM只会至多调用finalize一次,即使该对象“复活”也是如此。程序员手动调用多少次不影响JVM的行为
- 若JVM检测到finalized状态的对象变成unreachable,回收其内存(I)
- 若对象并未覆盖finalize方法,JVM会进行优化,直接回收对象(O)
- 注:System.runFinalizersOnExit()等方法可以使对象即使处于reachable状态,JVM仍对其执行finalize方法
4. 一些代码示例
(1) 对象复活
- publicclass
publicstaticnull
publicstaticvoidthrows
new
null);
- ifnull
- else
null
);
- ifnull
else
- protectedvoidthrows
superthis
}
(2)覆盖finalize方法以确保资源释放
作为一个补充操作,以防用户忘记“关闭“资源,JDK中FileInputStream、FileOutputStream、Connection类均用了此”技术“,下面代码摘自FileInputStream类
- /**
- * Ensures that the <code>close</code> method of this file input stream is
- * called when there are no more references to it.
- *
- * @exception IOException if an I/O error occurs.
- * @see java.io.FileInputStream#close()
- */
protectedvoidthrows
ifnull* will ensure that finalizer is only called when
- * safe to do so. All references using the fd have
- * become unreachable. We can call close()
- */
}
参考:
12.6 Finalization of Class Instances https://notendur.hi.is//~snorri/SDK-docs/lang/lang083.htm深入理解java的finalize http://zhang-xzhi-xjtu.iteye.com/blog/484934The Finalizable Object http://www.artima.com/interfacedesign/Finalizable.htm
Android内存优化4 了解java GC 垃圾回收机制2 GC执行finalize的过程的更多相关文章
- 浅析JAVA的垃圾回收机制(GC)
1.什么是垃圾回收? 垃圾回收(Garbage Collection)是Java虚拟机(JVM)垃圾回收器提供的一种用于在空闲时间不定时回收无任何对象引用的对象占据的内存空间的一种机制. 注意:垃圾回 ...
- JAVA的垃圾回收机制(GC)
1.什么是垃圾回收? 垃圾回收(Garbage Collection)是Java虚拟机(JVM)垃圾回收器提供的一种用于在空闲时间不定时回收无任何对象引用的对象占据的内存空间的一种机制. 2.什么时候 ...
- java面试题之----JVM架构和GC垃圾回收机制详解
JVM架构和GC垃圾回收机制详解 jvm,jre,jdk三者之间的关系 JRE (Java Run Environment):JRE包含了java底层的类库,该类库是由c/c++编写实现的 JDK ( ...
- JVM和GC垃圾回收机制和内存分配
JVM运行期间 线程共享 线程私有 线程共享: 方法区 堆方法区:存放可以共享数据,静态常量,类的共有方法属性字段等,可以共享的存在方法区. 堆:存放class对象 . 线程私有:本地方法栈 虚拟机栈 ...
- 面试官,不要再问我“Java GC垃圾回收机制”了
Java GC垃圾回收几乎是面试必问的JVM问题之一,本篇文章带领大家了解Java GC的底层原理,图文并茂,突破学习及面试瓶颈. 楔子-JVM内存结构补充 在上篇<JVM之内存结构详解> ...
- 乐字节Java|GC垃圾回收机制、package和import
本文接上一篇:乐字节Java|this关键字.static关键字.block块.本文是接着讲述JavaGC垃圾回收机制.package 和 import语句. 一.GC垃圾回收机制 GC全名:Garb ...
- Java垃圾回收机制(GC策略)
Java垃圾回收机制(GC策略) 核心:1,哪些是垃圾?[怎么确定这个是垃圾]:2,如何回收垃圾?[怎么更好收垃圾]. Java语言相对于C++等语言有一个自动垃圾回收机制,只用管使用[实例化对象], ...
- 记录Java的垃圾回收机制和几种引用
一.Java的垃圾回收机制 Java的垃圾回收机制(java garbage collection)是Java虚拟机提供的能力,用于在空闲时间以不定时的方式动态回收无任何引用的对象占据的堆内存空间. ...
- 了解java中垃圾回收机制
Java的垃圾回收机制是Java环境自带有的,它不像c语言的malloc申请空间后需要Free()函数来释放,而Java中的代码块中所申请的空间可在程序执行完成后自动释放,但是是有局限性的,代码块所占 ...
随机推荐
- mongodb循环
var rds = db.REGIPATIENTREC.find({mzh:{$lt:"0"},usrOrg:"石景山中西医结合医院"}); var show ...
- java常用设计模式学习心得
学习自:http://shenzhenchufa.blog.51cto.com/730213/161581 代码来自:http://shenzhenchufa.blog.51cto.com/73021 ...
- Proxy那点事儿
全文转载,原文地址:Proxy 那点事儿 Proxy,也就是"代理"了.意思就是,你不用去做,别人代替你去处理.比如说:赚钱方面,我就是我老婆的 Proxy:带小孩方面,我老婆就是 ...
- C语言 反序打印字符串中的单词
int main() { char *str = "see you later"; int r = strlen(str); char * p = str; ; while(*st ...
- AC日记——「SCOI2015」情报传递 LiBreOJ 2011
#2011. 「SCOI2015」情报传递 思路: 可持久化树状数组模板: 代码: #include <bits/stdc++.h> using namespace std; #defin ...
- mp4文件格式解析(转载)
mp4文件格式解析 原作:http://blog.sina.com.cn/s/blog_48f93b530100jz4b.html 目前MP4的概念被炒得很火,也很乱.最开始MP4指的是音频(MP3的 ...
- Ubuntu 18.04安装网易云音乐(转载)
作为Ubuntu下唯一一款超级好用的音乐软件,必须下载. 提升为root权限后操作 0 : 网易云音乐1.0.0(该版本较为好安装)下载地址 http://s1.music.126.net/downl ...
- oracle 自己改了 spfile 导致起不来
oracle pfile 出错 今天在升级 oracle 内存的时候参数调错了,导致 oracle 起不来, 情急之下用 vim 修改了 spfile 文件,结果由于该文件是二进制的,不能直接修改,所 ...
- NBUT 1218 You are my brother
$dfs$. 记录一下每一个节点的深度就可以了. #include<cstdio> #include<cstring> #include<cmath> #inclu ...
- SpringBoot整合SpringSecurity简单实现登入登出从零搭建
技术栈 : SpringBoot + SpringSecurity + jpa + freemark ,完整项目地址 : https://github.com/EalenXie/spring-secu ...