Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android開發經驗—不要指望類的finalize方法干你想要干的活

Android開發經驗—不要指望類的finalize方法干你想要干的活

編輯:關於Android編程

之所以專門寫一篇關於finalize方法的博客,是因為被這個方法坑過,在寫一個讀取jni數據類的時候,我在類的finalize方法中調用了關閉文件和釋放內存的方法,結果導致在頻繁調用這個類的時候在JNI裡面報異常,類本來就是單例的,按理分析不應該存在這樣的情況,到最後分析出來就是因為在該類的finalize方法中調用了關閉文件的方法,導致下次進入再次打開文件時,被系統調用finalize方法給關閉掉了,出現異常的代碼如下。

public class TraceHandle{
    static{
        try{
            System.loadLibrary("TraceHandle");
        }catch (UnsatisfiedLinkError ule){
            Log.e("JNI", "WARNING: Could not load TraceHandle.so");
        }
    }

    private TraceHandle( String filePath ){
        mFilePath = filePath;
        open( filePath );
    }

    /**
     * 實例化TraceHandle
     * 
     * */
    public static TraceHandle create( String filePath ){
        if (null == mTraceHandle){
            mTraceHandle = new TraceHandle( filePath);
        }

        mTraceHandle.mInitCount++;

        return mTraceHandle;
    }

    /**
     * 退出時銷毀TraceHandle
     * 
     * @return null.
     */
    public TraceHandle destory( ){
        mInitCount--;
        if (mInitCount == 0 && mTraceHandle != null){
            mTraceHandle.close();
            mTraceHandle = null;
        }

        return null;
    }

    private void celan(){
        if (mTraceHandle != null){
            mTraceHandle.close();
            mTraceHandle = null;
        }
    }

    @Override
    protected void finalize() throws Throwable{
        super.finalize();
        //這是被系統調用的方法,系統會根據系統環境來調用,對於程序來說它的調用實際不可預見
        celan();
    }
    

    // 1、打開文件
    private native int open(String tracePath );

    // 2、搜索指定漢字
    private native int[] search(byte[] wordArray);

    // 3、必須關閉文件
    private native boolean close();
    

    private int mInitCount = 0;
    private String mFilePath = null;
    private static TraceHandle mTraceHandle = null;
}

經過查閱資料和閱讀《JAVA核心技術》裡面相關的章節後,問題終於搞定。在《JAVA核心技術》一書中是這樣描述finalize方法的:

“可以為任何一個類添加finalize方法。finalize方法將在垃圾回收器清除對象之前調用。在實際應用中,不要依賴於使用finalize方法回收任何短缺的資源,這是因為很難知道這個方法什麼時候才能夠調用。

如果某個資源需要在使用完畢立刻被關閉,那麼就需要由人工來管理。可以應用一個類似dispose或close的放來完成相應的清理操作。特別需要說明,如果一個類使用了這樣的方法,當對象不再被使用時一定要調用它。”

修改後的代碼如下,去掉了finalize方法:

public class TraceHandle{
    static{
        try{
            System.loadLibrary("TraceHandle");
        }catch (UnsatisfiedLinkError ule){
            Log.e("JNI", "WARNING: Could not load TraceHandle.so");
        }
    }

    private TraceHandle( String filePath ){
        mFilePath = filePath;
        open( filePath );
    }

    /**
     * 實例化TraceHandle
     * 
     * */
    public static TraceHandle create( String filePath ){
        if (null == mTraceHandle){
            mTraceHandle = new TraceHandle( filePath);
        }

        mTraceHandle.mInitCount++;

        return mTraceHandle;
    }

    /**
     * 退出時銷毀TraceHandle
     * 
     * @return null.
     */
    public TraceHandle destory( ){
        mInitCount--;
        if (mInitCount == 0 && mTraceHandle != null){
            mTraceHandle.close();
            mTraceHandle = null;
        }

        return null;
    }

    private void celan(){
        if (mTraceHandle != null){
            mTraceHandle.close();
            mTraceHandle = null;
        }
    }

    // 1、打開文件
    private native int open(String tracePath );

    // 2、搜索指定漢字
    private native int[] search(byte[] wordArray);

    // 3、必須關閉文件
    private native boolean close();
    

    private int mInitCount = 0;
    private String mFilePath = null;
    private static TraceHandle mTraceHandle = null;
}

由於java有自己的垃圾回收機制,所以在寫代碼的時候千萬不能依賴於它的一些方法來回收資源(比如finalize,gc),因為這些方法的調用時機都是不可預知的。

參考資料:

1、Why not to use finalize() method in java

2、When is the finalize() method called in Java?


  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved