程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> MMgc: The Garbage Collector of Flash Player

MMgc: The Garbage Collector of Flash Player

編輯:C++入門知識

MMgc是Flash Player中所使用的memorymanagementgarbagecollector。MMgc不僅是用來回收ActionScript中的對象,它也用來管理Flash Player中的所有動態內存分配、釋放請求,Flash Player VM的C++代碼中也有很多對象是交給MMgc自動回收的。所以,從理論上來說,MMgc可以從Flash Player的代碼中分離出來,作為一個單獨的GC庫,給所有C++程序用。
在MMgc中,堆上的對象被分為兩種,Managed和UnManaged。Managed的就是交給GC去管理,用戶只管new,不用delete,但是你也可以手動delete。UnManaged的就是傳統的C++中的那些對象,必須手動的new/delete。
所有Managed對象必須從class GCObject(或其子類)繼承。這個類增加了new和delete方法:
class GCObject{
       static void *operator new(size_t size, GC *gc, size_t extra) ;
       static void *operator new(size_t size, GC *gc) ;
       static void operator delete(void *gcObject);
};
假如一個類從GCObject繼承,例如
class MyPoint2D : public MMgc::GCObject {
    int x;
    int y;
};
那麼我們既可以像以前那樣直接new:
MyPoint2D* p = new MyPoint2D(); //這樣得到的對象是不受GC管理的。
也可以傳遞一個gc對象給new:www.2cto.com
MyPoint2D* p = new (gc) MyPoint2D(); //這樣得到的對象受GC管理。不需要delete
後面這種的語法看起來很像帶placeholder的new,但其實不是。
從Managed對象指向Managed對象,要加一個write barrier ,叫DWB。
class MyOtherManagedObject : public MMgc::GCObject { DWB(MyPoint2D*) object; };
對於那些不受GC管理的對象,要麼它跟GC一點關系都沒有,如std::string。要麼,如果它裡面包含了指向Managed對象的指針,那麼這個類必須從GCRoot繼承:
class MyUnmanagedObject : public MMgc::GCRoot { MyPoint2D * point; };
顧名思義,這些處於分界點上的對象,是GC的起點。執行GC的時候,從這些對象開始,挨個的mark-sweep。
但是僅僅這樣還不夠,如果某個成員變量的類型是指針,指針指向的是Managed對象,還得加一個write barrier 。即,上面的例子得改成:
class MyUnmanagedObject : public MMgc::GCRoot {DRC(MyPoint2D) * point; };
對於其它類型的不用加:
class MyUnmanagedObject : public MMgc::GCRoot {DRC(MyPoint2D) * point;  std::string* name; };
另外就是析構函數的問題。眾所周知,JAVA這樣的帶GC的語言中,都是沒有析構函數的。你要實在想用,有finalize方法。對此,MMgc的做法是,把基類從GCObject 改成GCFinalizedObject。
GCFinalizedObject還有一個子類叫RCObject。這個對象會帶一個類型為uint32_t的字段做引用計數。一旦count到0,就立馬free。這樣的話,釋放內存更為即時,從而降低GC的壓力。但是,write barrier 得從DWB換成DRCWB。
並且,對於RCObject對象,必須在它的析構函數中把所有成員變量都清0。
所以,雖然使用了MMgc就避免了手動delete,但是也帶來了很多用錯的風險,如:
1. 用錯write barrier。DWB、DRCWB、DRC用錯或漏寫,或者不該加的地方加了。
2. unmanaged object沒有從GCRoot繼承。
不過這些問題基本都是在編譯期很容易發現的,通過檢查類的定義就可以看出。
MMgc現在其實有兩套實現,一套是conservative gc,一套是exact gc。conservative gc有一個問題是,它並不能准確的判斷指針和整數。從而,如果有一個int恰好它的值等於某個對象的地址,這個對象就因此多了一個虛假的引用,從而一直不能被釋放。但是Adobe的想法是,這不是一個大問題。因為這種事情出現的概率很隨機,不至於因此而導致內存一直猛漲。www.2cto.com
前面用到的DRC宏,其中DRC是Deferred Reference Counting的縮寫。Deferred 的意思是說,並非到了0就立馬清除。這是因為,GC管理的只是堆上的東西,如果棧上有一個指針指向了這個對象,那麼GC並不知道。count==0的RCObject對象會被放到一個叫做Zero Count Table(ZCT)的表中,然後在適當的時候通過回溯整個棧的方式,找出引用關系,然後把沒有被引用的清理掉。
Flash的vm已經開源,叫tamarin,由Mozilla基金會管理。它裡面含有MMgc的全部代碼。我試圖把MMgc單獨剝離出來,但是不大容易。因為MMgc不僅依賴於下面的OS適配層,還依賴於VM core裡面的一些代碼(String、Math、Date)等。去掉memory profiler也許會好點。
我後來想想,別的程序想用MMgc估計也不大容易,因為MMgc是單線程的。現在單線程的程序愈來愈少了。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved