Netty小記——引用計數機制

引用計數機制在很多框架中都有使用,如果在遊戲引擎框架coscos2dx中,這種機制可以很簡單的進行對象的生命週期的管理,netty引用計數機制原文:http://netty.io/wiki/reference-counted-objects.html

Since Netty version 4, the life cycle of certain objects are managed by their reference counts, so that Netty can return them (or their shared resources) to an object pool (or an object allocator) as soon as it is not used anymore. Garbage collection and reference queues do not provide such efficient real-time guarantee of unreachability while reference-counting provides an alternative mechanism at the cost of slight inconvenience.

從netty的4.x版本開始,netty使用引用計數機制進行部分對象的管理,通過該機制netty可以很好的實現自己的共享資源池。如果應用需要一個資源,可以從netty自己的共享資源池中獲取,新獲取的資源對象的引用計數被初始化爲1,可以通過資源對象的retain方法增加引用計數,當引用計數爲0的時候該資源對象擁有的資源將會被回收。
這種方式相比於jvm的垃圾回收機制和引用隊列機制來說更加實時高效,但是犧牲了一部分易用性。

資源初始化的時候引用計數爲1

ByteBuf buf = ctx.alloc().directBuffer();
assert buf.refCnt() == 1;

當需要釋放資源的時候,調用release函數會將引用計數減一(release僅僅是減少引用計數,當引用計數爲0的時候才進行回收)

assert buf.refCnt() == 1;
// release() returns true only if the reference count becomes 0.
boolean destroyed = buf.release();
assert destroyed;
assert buf.refCnt() == 0;

如果資源對象的引用計數爲0的時候,如果應用程序繼續使用那麼會拋出IllegalReferenceCountExeception異常

assert buf.refCnt() == 0;
try {
  buf.writeLong(0xdeadbeef);
  throw new Error("should not reach here");
} catch (IllegalReferenceCountExeception e) {
  // Expected
}

如果資源對象需要在多個邏輯中使用,可以通過retain來增加引用計數,從而可以避免引用計數爲0時引起的異常引用的異常

ByteBuf buf = ctx.alloc().directBuffer();
assert buf.refCnt() == 1;

buf.retain();
assert buf.refCnt() == 2;

boolean destroyed = buf.release();
assert !destroyed;
assert buf.refCnt() == 1;

誰負責釋放資源,最後使用資源的負責釋放資源,具體查看原文例子

如果netty自帶的部分decode類返回的對象是引用計數的,那麼只需要使用者在最後一個處理該自定義的handler中調用release方法即可(但是一定要調用,否則會造成內存泄漏

同樣的在outbound handler中,如果應用層使用了帶引用計數的對象,那麼在outbound的pipeline的最後一個使用該對象的handler應該負責reease該對象,否則會出現內存泄漏

The disadvantage of reference counting is that it is easy to leak the reference-counted objects. Because JVM is not aware of the reference counting Netty implements, it will automatically GC them once they become unreachable even if their reference counts are not zero. An object once garbage collected cannot be resurrected, and thus cannot be returned to the pool it came from and thus will produce memory leak.
內存泄漏:在netty中的內存泄漏是指GC自動回收了refCnt>0的對象的內存,這種情況下使得該對象無法被重建,同時也無法被歸還回到netty自己的緩衝區中,所以即使該內存被jvm GC可用了,但是應用層仍然標誌了該內存被使用中,從而使得該塊內存在應用的整個生命週期中無法被使用,造成了浪費。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章