final finally finalized区别

来源:互联网 发布:mac不允许写访问 编辑:程序博客网 时间:2024/05/16 09:49

final

1.final,是java关键字,可以修饰类,方法,变量。
2. final类不能被继承,final方法不能被重写,final变量不能被修改,并且必须在声明时赋值。

finally

1.finally,是java异常机制中的子语句
2.在执行完try~catch后执行finally语句,无论try语句中有没有异常,finally语句都将执行
3.如果try语句中有return语句,则先执行finally语句 再执行return
4.如果try语句中程序退出(System.exit(0)),则不执行finally

finalized

说明:

1.finalize()是Object的protected方法,子类可以覆盖该方法以实现资源清理工作,GC在回收对象之前调用该方法,Object的默认finalize什么都不做
2.finalize()与C++中的析构函数不是对应的。C++中的析构函数调用的时机是确定的(对象离开作用域或delete掉),但Java中的finalize的调用具有不确定性
3.不建议用finalize方法完成“非内存资源”的清理工作,但建议用于:① 清理本地对象(通过JNI创建的对象);② 作为确保某些非内存资源(如Socket、I/O等)释放的一个补充:在finalize方法中显式调用其他资源释放方法。
4.finalize方法至多由GC执行一次(用户当然可以手动调用对象的finalize方法,但并不影响GC对finalize的行为)

对象的两种状态:

一是终结状态空间 F = {unfinalized, finalizable, finalized}(针对重写了finalized方法的类);二是可达状态空间 R = {reachable, finalizer-reachable, unreachable}。各状态含义如下:
unfinalized: 新建对象会先进入此状态,GC并未准备执行其finalize方法,因为该对象是可达的
finalizable: 表示GC可对该对象执行finalize方法,GC已检测到该对象不可达。正如前面所述,GC通过F-Queue队列和一专用线程完成finalize的执行
finalized: 表示GC已经对该对象执行过finalize方法
reachable: 表示GC Roots引用可达
finalizer-reachable(f-reachable):表示不是reachable,但可通过某个finalizable对象可达
unreachable:对象不可通过上面两种途径可达

finalize的执行过程(生命周期):

(1)finalize大概流程:当对象变成(GC Roots)不可达时,GC会判断该对象是否覆盖了finalize方法,若未覆盖,则直接将其回收。否则,若对象未执行过finalize方法,将其放入F-Queue队列,由一低优先级线程执行该队列中对象的finalize方法。执行finalize方法完毕后,GC会再次判断该对象是否可达,若不可达,则进行回收,否则,对象“复活”。

状态变迁图:

这里写图片描述

变迁说明:
1.新建对象首先处于[reachable, unfinalized]状态(A)
2.随着程序的运行,一些引用关系会消失,导致状态变迁,从reachable状态变迁到f-reachable(B, C, D)或unreachable(E, F)状态
3.若JVM检测到处于unfinalized状态的对象变成f-reachable或unreachable,JVM会将其标记为finalizable状态(G,H)。若对象原处于[unreachable, unfinalized]状态,则同时将其标记为f-reachable(H)。
4.在某个时刻,JVM取出某个finalizable对象,将其标记为finalized并在某个线程中执行其finalize方法。由于是在活动线程中引用了该对象,该对象将变迁到(reachable, finalized)状态(K或J)。该动作将影响某些其他对象从f-reachable状态重新回到reachable状态(L, M, N)
5.处于finalizable状态的对象不能同时是unreahable的,由第4点可知,将对象finalizable对象标记为finalized时会由某个线程执行该对象的finalize方法,致使其变成reachable。这也是图中只有八个状态点的原因
6.程序员手动调用finalize方法并不会影响到上述内部标记的变化,因此JVM只会至多调用finalize一次,即使该对象“复活”也是如此。程序员手动调用多少次不影响JVM的行为
7.若JVM检测到finalized状态的对象变成unreachable,回收其内存(I)
8.若对象并未覆盖finalize方法,JVM会进行优化,直接回收对象(O)
9.注:System.runFinalizersOnExit()等方法可以使对象即使处于reachable状态,JVM仍对其执行finalize方法

一些代码示例

(1) 对象复活

<code class="hljs cs has-numbering"><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> GC {      <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> GC SAVE_HOOK = <span class="hljs-keyword">null</span>;      <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span>(String[] args) throws InterruptedException {          SAVE_HOOK = <span class="hljs-keyword">new</span> GC();          SAVE_HOOK = <span class="hljs-keyword">null</span>;          System.gc();          Thread.sleep(<span class="hljs-number">500</span>);          <span class="hljs-keyword">if</span> (<span class="hljs-keyword">null</span> != SAVE_HOOK) { <span class="hljs-comment">//此时对象应该处于(reachable, finalized)状态  </span>            System.<span class="hljs-keyword">out</span>.println(<span class="hljs-string">"Yes , I am still alive"</span>);          } <span class="hljs-keyword">else</span> {              System.<span class="hljs-keyword">out</span>.println(<span class="hljs-string">"No , I am dead"</span>);          }          SAVE_HOOK = <span class="hljs-keyword">null</span>;          System.gc();          Thread.sleep(<span class="hljs-number">500</span>);          <span class="hljs-keyword">if</span> (<span class="hljs-keyword">null</span> != SAVE_HOOK) {              System.<span class="hljs-keyword">out</span>.println(<span class="hljs-string">"Yes , I am still alive"</span>);          } <span class="hljs-keyword">else</span> {              System.<span class="hljs-keyword">out</span>.println(<span class="hljs-string">"No , I am dead"</span>);          }      }      @Override      <span class="hljs-keyword">protected</span> <span class="hljs-keyword">void</span> <span class="hljs-title">finalize</span>() throws Throwable {          super.finalize();          System.<span class="hljs-keyword">out</span>.println(<span class="hljs-string">"execute method finalize()"</span>);          SAVE_HOOK = <span class="hljs-keyword">this</span>;      }  }  </code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li><li>24</li><li>25</li><li>26</li><li>27</li><li>28</li><li>29</li><li>30</li><li>31</li></ul>

(2)覆盖finalize方法以确保资源释放
作为一个补充操作,以防用户忘记“关闭“资源,JDK中FileInputStream、FileOutputStream、Connection类均用了此”技术“,下面代码摘自FileInputStream类

<code class="hljs java has-numbering"><span class="hljs-javadoc">/**  * Ensures that the <code>close</code> method of this file input stream is  * called when there are no more references to it.  *  *<span class="hljs-javadoctag"> @exception</span>  IOException  if an I/O error occurs.  *<span class="hljs-javadoctag"> @see</span>        java.io.FileInputStream#close()  */</span>  <span class="hljs-keyword">protected</span> <span class="hljs-keyword">void</span> <span class="hljs-title">finalize</span>() <span class="hljs-keyword">throws</span> IOException {      <span class="hljs-keyword">if</span> ((fd != <span class="hljs-keyword">null</span>) &&  (fd != FileDescriptor.in)) {          <span class="hljs-comment">/* if fd is shared, the references in FileDescriptor          * will ensure that finalizer is only called when          * safe to do so. All references using the fd have          * become unreachable. We can call close()          */</span>          close();      }  }  </code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li></ul>

参考:http://blog.csdn.net/pi9nc/article/details/12374049


0 0
原创粉丝点击