windows系統使用c++實現自動垃圾回收的小demo

  自從疫情爆發以來,過得挺充實,天天學習,樂此不疲。  可惜就是把實習工作給戳脫了,不然就完美。哈哈哈,不過這段時間的收穫還是很足很足的,朕心甚悅!!  這段時間主要在加強對c++ 的學習,練習了很多小的demo,通過對相對底層語言的學習實踐,達到掌握很多高層知識的目的(事實上,很多知識記了又忘,忘了又記,惡性循環的原因在於理解的深度不夠)。

  接觸了java三年多,大部分知識自學,一直聽說什麼什麼垃圾回收,內存模型啥啥啥的,也看過很多相關的資源,始終是透着一層薄薄的窗戶紙,若隱若現,很不痛快。這個小demo的目的就在於,揭開它神祕的面紗,看看其廬山真貌。此外,也涉及到對Java相關知識的理解,如爲什麼所有類都是Object的子類爲什麼類加載器機制爲雙親委派模型爲什麼java中去除了指針?  也涉及到一些對跨平臺的理解,如: 爲什麼java語言跨平臺如此重要? 希望能夠幫到有需要學習的小夥伴。

  首先,通過查閱資料,得知如下的信息:

         1.java中的垃圾回收機制,使用標記清除法,即從內存中的所有根對象進行遍歷,設置其可達狀態,對不可達的對象釋放其內存。

        2.遍歷操作,數據量小還好,如果數據量巨多,同時,gc調用頻繁,回收率很低的話,則整體的性價比太低。爲了解決這個問題,通過 代際回收 來解決。 即所謂的 新生代,老年代,持久代。

       3.要進行垃圾回收,所有的對象必須j派生於一個公共的類。

  接下來開擼:

定義公共祖先類,相當於Java的Object

定義容器,保存對象的地址:

實現祖先類中的關鍵方法:

接着,定義一些測試子類:

最後,爲了較爲優雅的實現 對根對象的維護,我採用了一個對象工廠來進行維護,所有的對象均由工廠生成(因爲我暫時找不到更好的抽象模擬根對象,此外,這個實現不是線程安全的)。

測試代碼:

  以上,就是本次小demo的核心結構,和關鍵代碼。現在,來回答本文一開始提出的相關問題。

1.爲什麼所有類都要派生至一個祖先類?

    答:一方面,統一接口規範; 最根本原因在於,可以隱式實現對象的收集! (此外,我認爲跟子類代碼偏移之類啥的關係不大。因爲一個無狀態指針完全可以 指定爲任意類型的指針,舉個例子: void* a;  a =(void*)(new int(1))  是可以的,a=(void*)(new long(1))  也是可以的。)。

2.爲什麼java中需要使用雙親委派機制?

   答:從第一問可知,祖先類的唯一性十分重要,因此Object的是必須首先要保證唯一性的,這涉及到java的根源,之後我在實現jvm的小demo中,也會進一步驗證。

3.爲什麼java中去除了指針?

  答:在c++中,我們的對象實際上有兩種生成方式,其一爲 "Object o;"  注意,這跟java很很大差別,它實際上是棧分配的內存,在代碼出棧的時候,該內存會被回收。  所謂的出棧,入棧,其標識爲代碼塊,即{ code ...} 部分。其二爲"Object* o=new Object();",這個跟java就是一樣的了,=左邊我們稱之爲 左值,它是一個指針,指向new Object()的首地址,右值爲堆分配的內存,它代表了這個對象在內存中的映像,它的表現是一個地址。

       棧分配的對象,在出棧時會自動回收,這本該是一個好事,但是考慮一種情況,如果我要跨域 使用對象呢??

       堆分配的內存,滿足了跨域使用的要求,但是它不會自動釋放的(當然,程序結束後,會釋放掉)。 我們當然可以選擇手動釋放,但是手動釋放會遇到一些問題,如: 跨域使用的對象,我何時刪除?  當程序足夠大,對象足夠多,這將是一個可怕的工程,任何一個不當的操作都會導致災難!  當然了,也可以粗暴的選擇不釋放,最終結果就是內存耗盡,系統健全的話,程序異常結束;系統不健全的話,導致重啓。非常不幸的是,我還就曾經導致了這樣的問題,至今回想起來還心有餘悸。我的筆記本是捨不得的,還好是東家的老臺式。

       爲了兼容二者吧,java就引入了真命天子 ——gc,就規定了,所有的內存均由 垃圾回收器進行回收,即不是棧自動回收,也不是手動回收。 所謂沒有對比就沒有傷害,沒了棧分配變量,對分配變量指針自然也就不叫了,我是這樣理解的。還沒去查資料,權當自娛自樂吧。

4.爲什麼跨平臺如此重要?

    答: 這是我在較爲系統的使用c++進行編碼實踐的時候面臨的第一大問題,網上很多的例子使用的都是linux進行實現,linux與windows的一些api存在差別,而恰好,這些api對我來說又是十分關鍵的。 如線程: linux的pthread,windows的原生api,文件操作的區別,socket套接字的區別。。。   我才猛然回想起,好像我不是菜鳥啊?  接觸編程也挺久了,以前java感覺用的飛起,不論是Linux開發部署也好,windows開發部署也好! 

     此時,腦海中回想起 課桌上,某老師跟我們說java是跨平臺的語言,xxxxxxx。。 嗯,明白了,跨平臺,真不只是說說而已,其中的酸楚只有趟過坑的人才會對 ”跨平臺“,愛得深沉,愛的熱烈。   想想一個APP,需要同時開發多個端的痛苦吧,ios,android,h5,小程序等等,最操蛋的是,它們明明功能都是一樣的,樣的,的。。。。。   


附上這個小demo的github地址,所有代碼均在裏面,有小夥伴感興趣的也可以留言討論哦!

地址

另外,這篇文章寫得既不繫統,也不詳細。  超級推薦先看一下這篇文章,本demo可以說完全基於它進行實現(原帖時間過於久遠,我找他文中的資源已經找不到了。):

自己動手,用C++實現垃圾回收系統

我的開發環境是:windows10 + mingw64 + clion + cmake

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