5
FileInputStream / FileOutputStream Considered Harmful | CloudBees (www.cloudbees.com)
caterpillar 積分 4 編輯於

Java 9 廢棄了 finalize 方法,FileInputStream 等也清空了 finalize 方法的實作,改用 PhantomReference 的機制,JVM 有個執行緒會監控 Reference,在實例不再被參考時,呼叫 close 方法。

至於相容性的部份,若有 FileInputStream 的子類,且自定義了 close 方法,實例化時會有個 AltFinalizer 產生,AltFinalizer 建立時會包裹 FileInputStream,AltFinalizer 的作用就是等著被回收時,呼叫自定義的 finalize 方法(被加了 @SuppressWarnings("deprecation")),其中呼叫了 FileInputStream 的 close 方法。

繞來繞去的 ...

caterpillar 積分 1 編輯於

Every time you create either a FileInputStream or a FileOutputStream you are creating an object, even if you close it correctly and promptly, it will be put into a special category that only gets cleaned up when the garbage collector does a full GC.

就算自己 close 了也不是真的 close 了?還是得依賴 Full GC 呼叫 finalize 才會真的 close?有所謂的 a special category?

   public void close() throws IOException {
        synchronized (closeLock) {
            if (closed) {
                return;
            }
            closed = true;
        }
        if (channel != null) {
           channel.close();
        }

        fd.closeAll(new Closeable() {
            public void close() throws IOException {
               close0();
           }
        });
    }

    protected void finalize() throws IOException {
        if ((fd != null) &&  (fd != FileDescriptor.in)) {
            /* 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()
             */
            close();
        }
    }

如果他的意思是因為 override 了 finalize,所以會被排入 GC 時得呼叫 finalize,那也很奇怪, finalize 一直都在那啊?還是說他的意思是,finalize 裡寫的程式碼檢查會造成不必要的開銷?

去看看別的地方的 comments,也有人覺得這說法不太對。

FileInputStream / FileOutputStream Considered Harmful1

koji 積分 2 編輯於

應該是你說的第二點,非 trivial finalize() 的 instance 會被丟到 finalize queue。 關於trivial finalize()1

IngramChen 積分 1

很久很久以前好像踩過這個雷,在小物件上加了 finalize 然後就 OOM 了

koji 積分 1

印象還有 cubie server 那時我們追 memory leak 時看到一堆物件在 finalize queue。

caterpillar 積分 0

因此跟 close 沒有直接關係,而是因為定義了 finalize 會使得該物件在 Full GC 時才真的被處理掉。

koji 積分 0

full gc 可能不太精確,不一定是 full gc phase。