日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

java手动回收_浅谈java是如何做资源回收补救的

發布時間:2023/12/2 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java手动回收_浅谈java是如何做资源回收补救的 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

學習java的過程,我們經常談論一個對象的回收,尤其是資源類型,如果沒有顯示的關閉,對象就被回收了,說明出現了資源泄漏。java本身為了防止這種情況,做了一些擔保的方式,確保可以讓未關閉的資源合理回收掉。

finalize回收

finalize方式是java對象被回收時觸發的一個方法。java的很多資源對象,都是在finalize中寫了擔保的方法。

/**

* Ensures that the close 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()

*/

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();

}

}

上面是FileInputStream的finalize方法,在方法被調用時,會檢測文件描述符是否存在,如果存在的話就調用close方法。來確保資源的回收。

finalize方法在我們學習java的時候都并不推薦進行重寫,也不推薦寫復雜的邏輯在里面,主要是因為gc的時候,都會調用這個方法,如果執行的內容太多,就會導致gc被拖長。影響程序的正常運行。而且這里也只是做一個簡單的擔保。大部分希望的還是編寫代碼的人可以調用close。這樣在做判斷的時候就結束了,而不用真正的調用關閉的代碼。

Cleaner回收

在DirectByteBuffer中,使用了一個Cleaner對象進行補救的。

unsafe.setMemory(base, size, (byte) 0);

if (pa && (base % ps != 0)) {

// Round up to page boundary

address = base + ps - (base & (ps - 1));

} else {

address = base;

}

cleaner = Cleaner.create(this, new Deallocator(base, size, cap));

att = null;

申請完資源后,會創建一個Deallocator對象。

private static class Deallocator

implements Runnable

{

private static Unsafe unsafe = Unsafe.getUnsafe();

private long address;

private long size;

private int capacity;

private Deallocator(long address, long size, int capacity) {

assert (address != 0);

this.address = address;

this.size = size;

this.capacity = capacity;

}

public void run() {

if (address == 0) {

// Paranoia

return;

}

unsafe.freeMemory(address);

address = 0;

Bits.unreserveMemory(size, capacity);

}

}

Deallocator的run方法中就進行了資源的釋放。執行的時機就是靠 Cleaner來觸發的。

Cleaner是PhantomReference的子類,PhantomReference是Reference的子類。

在中有一個ReferenceHandler

private static class ReferenceHandler extends Thread {

他的run方法就是調用cleaner里的clean方法。這個線程是在靜態塊里啟動起來的。

Thread handler = new ReferenceHandler(tg, "Reference Handler");

/* If there were a special system-only priority greater than

* MAX_PRIORITY, it would be used here

*/

handler.setPriority(Thread.MAX_PRIORITY);

handler.setDaemon(true);

handler.start();

SharedSecrets.setJavaLangRefAccess(new JavaLangRefAccess() {

@Override

public boolean tryHandlePendingReference() {

return tryHandlePending(false);

}

});

于此同時,并且給SharedSecrets設置了一個JavaLangRefAccess。

調用clean方法的過程在tryHandlePending里,這里的參數很重要。

static boolean tryHandlePending(boolean waitForNotify) {

Reference r;

Cleaner c;

try {

synchronized (lock) {

if (pending != null) {

r = pending;

// 'instanceof' might throw OutOfMemoryError sometimes

// so do this before un-linking 'r' from the 'pending' chain...

c = r instanceof Cleaner ? (Cleaner) r : null;

// unlink 'r' from 'pending' chain

pending = r.discovered;

r.discovered = null;

} else {

// The waiting on the lock may cause an OutOfMemoryError

// because it may try to allocate exception objects.

if (waitForNotify) {

lock.wait();

}

// retry if waited

return waitForNotify;

}

}

} catch (OutOfMemoryError x) {

// Give other threads CPU time so they hopefully drop some live references

// and GC reclaims some space.

// Also prevent CPU intensive spinning in case 'r instanceof Cleaner' above

// persistently throws OOME for some time...

Thread.yield();

// retry

return true;

} catch (InterruptedException x) {

// retry

return true;

}

waitForNotify是true的時候,在沒有回收對象的時候,會進入阻塞,然后等ooe。外層是個死循環,就會被再次調用到,下次進來的時候就可以出發clean了。

ReferenceHandler是管理機制的一種。

還有一種就是SharedSecrets調用tryHandlePending(false)。

在另外一個類,bits里

final JavaLangRefAccess jlra = SharedSecrets.getJavaLangRefAccess();

// retry while helping enqueue pending Reference objects

// which includes executing pending Cleaner(s) which includes

// Cleaner(s) that free direct buffer memory

while (jlra.tryHandlePendingReference()) {

if (tryReserveMemory(size, cap)) {

return;

}

}

在做reserveMemory的時候,會從SharedSecrets來調用tryHandlePending(false)。這里又變相的進行了一次回收。

小結

java回收利用兩種機制。一種是finalize,一種是Cleaner。其中Cleaner一部分依賴oome觸發一次回收,一部分利用reserveMemory中做一次回收。

到此這篇關于淺談java是如何做資源回收補救的的文章就介紹到這了,更多相關java 資源回收補救內容請搜索腳本之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持腳本之家!

總結

以上是生活随笔為你收集整理的java手动回收_浅谈java是如何做资源回收补救的的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。