第六章 垃圾回收

垃圾回收:

垃圾回收指的是程序運行過程中,檢查是否有不再使用的對象,并自動釋放他們所占用的內(nèi)存锄开,通常被簡稱為GC。內(nèi)存的檢查和回收都是由垃圾收集器完成的称诗。

在OC2.0中萍悴,垃圾回收首先進(jìn)行的工作就是識別不允許被回收的對象。全局變量寓免,靜態(tài)變量和棧內(nèi)臨時變量他們所引用的對象不允許被回收癣诱。這些對象稱為根集合。如果一個對象的實例變量引用了不允許被回收的對象或根集合中的對象袜香,那么這個對象也不允許被回收撕予。也就是說,通過全局變量蜈首,靜態(tài)變量或者棧內(nèi)變量的強(qiáng)引用而查找到的對象都不可以被回收实抡。反之,只要是從根集合出發(fā)無法到達(dá)的對象都屬于垃圾回收的目標(biāo)欢策。

對于不再使用的對象我們可以通過為其賦值nil來明確表示其已不再被使用吆寨,據(jù)此通知垃圾收集器回收該對象。這種做法不僅有助于垃圾回收猬腰,也是一種良好的編程風(fēng)格鸟废。

垃圾收集器整個回收過程完全是根據(jù)程序占用內(nèi)存的多少自動完成的。一個程序只有一個垃圾收集器姑荷,通常在mainthread中運行盒延。它通常作為一個單獨的線程運行。垃圾收集器運行的時候有可能會暫停其他線程來完成垃圾收集鼠冕。

主動啟動垃圾回收:通過給類NSGarbageCollector發(fā)送collectIfNeeded消息來啟動垃圾收集器添寺。通過主動啟動垃圾回收,不僅可以控制內(nèi)存消費懈费,又可以避免垃圾回收突然啟動時程序反應(yīng)變慢的問題计露。

finalize方法的定義:

finalize方法被定義在NSObject中,在對象被回收之前憎乙,finalize方法會被執(zhí)行票罐。原則上不推薦輕易定義finalize,因為finalize方法作為垃圾回收的一部分被執(zhí)行泞边,垃圾回收在一個獨立的線程中進(jìn)行该押。同軟件本身是并行關(guān)系,如果finalize處理過于復(fù)雜的話就會影響軟件本身的執(zhí)行速度阵谚。另外蚕礼,要被釋放的對象的finalize方法的執(zhí)行是沒有先后順序的烟具。不要依賴finalize方法的執(zhí)行順序來做任何事情。

實現(xiàn)finalize方法的時候要注意下面這些事項:

finalize方法內(nèi)不用擔(dān)心其他對象的釋放奠蹬。

要注意finalize方法中對象的賦值朝聋。

finalize的執(zhí)行順序和對象的釋放順序都是無法確定的。

finalize不是線程安全的囤躁。

對象的善后處理應(yīng)該在這個對象不再使用的時候進(jìn)行冀痕,而不要在finalize 方法中進(jìn)行。特別是文件之類的資源對象狸演,不要在finalize方法中進(jìn)行關(guān)閉處理金度。進(jìn)行善后處理之后,可以將不再使用的對象賦值為別的對象或者nil严沥,以取消對該對象的引用猜极,并告知垃圾收集器該對象可以被清理了。

反之消玄,在多個地方釋放對象時跟伏,就不得不用到finalize方法。

使用垃圾回收編程小結(jié):

·編譯的時候需要使用編譯選項fobjc-gc-only

·使用局部變量給方法中的局部對象賦值

·如果暫時不想垃圾回收某對象翩瓜,需要保證該對象能夠被全局變量引用

·原則上垃圾回收只負(fù)責(zé)回收id類型或類類型的變量

·不用考慮所有權(quán)的問題受扳,也不用考慮實例變量的問題

·釋放對象時的一些“善后”操作可以寫在finalize方法中,但除了不寫在finalize中就無法實

現(xiàn)的功能兔跌,要盡量減少通過finalize完成的操作

·引用計數(shù)相關(guān)的方法和dealloc方法不會被執(zhí)行

分代垃圾回收:

啟用垃圾回收后勘高,會在變量賦值,改寫變量時建立寫屏障坟桅。OC2.0利用修改變量時的信息采用分代垃圾回收的方式來進(jìn)行內(nèi)存管理华望。分代垃圾回收并不會每次對整個堆空間進(jìn)行遍歷,而是以新生成的對象為中心仅乓,以盡可能快速的收集那些生命周期短的對象赖舟,通過這種分代的方法,既可以減輕垃圾回收的處理負(fù)荷夸楣,又能有效釋放空間宾抓,但也要小心這種方法會積攢太多的陳舊對象。

弱引用:

和ARC不一樣的是豫喧,棧內(nèi)的臨時變量不能聲明為弱引用石洗。同時也可以使用_ _ strong修飾符來聲明一個變量是強(qiáng)引用類型。除了這兩個修飾符外紧显,_ _autoreleasing和_ _unsafe_unretained等其他生命期修飾符在垃圾回收中都不可用讲衫。

弱引用的作用在于解決強(qiáng)引用所帶來的對象之間在存活時間上的耦合關(guān)系。

盡量不要使用這種依賴于垃圾回收的運行頻率和時機(jī)的編程方法鸟妙。

通過垃圾回收回收動態(tài)分配的內(nèi)存:

通過NSAllocateCollectable()分配的內(nèi)存因為可以通過垃圾回收被自動回收焦人,所以可以不考慮內(nèi)存釋放的問題,比使用malloc和free編程更方便重父。但指向初對象之外的動態(tài)內(nèi)存的指針變量都需要用_ _strong來修飾花椭。另外,程序的效率有可能會降低房午,所以并不需要特意把原來使用的malloc/free的代碼都改為NSAllocateCollectable矿辽。

_ _ strong修飾符的使用方法:

修飾對象類型的變量。

修飾指針類型的變量郭厌。被_ _strong修飾的指針?biāo)赶虻膬?nèi)存可以被垃圾回收袋倔,但要等到該指針不再使用為止。

用于修飾函數(shù)或方法返回的指針類型折柠。指針指向的內(nèi)存屬于垃圾回收的范疇宾娜,但如果被賦值給一個強(qiáng)引用類型的變量,就暫時不能被回收扇售。

NSGarbageCollector類:

+ (id)defaultCollector ?//返回現(xiàn)在有效的垃圾收集器的實例前塔,如果垃圾收集無效,則返回nil承冰。

- (void)collectIfNeeded //申請進(jìn)行垃圾回收华弓。這個方法被調(diào)用之后會判斷當(dāng)前內(nèi)存使用情況,如果覺得需要進(jìn)行垃圾回收就會啟動垃圾收集器困乒。典型的調(diào)用方式如下:

[[NSGarbageCollectordefaultCollector]collectIfNeeded];

- (void)collectExhaustively //申請進(jìn)行垃圾回收寂屏。希望使用深度遍歷以盡可能地釋放更多的內(nèi)存時使用。這個方法被調(diào)用之后會判斷當(dāng)前內(nèi)存使用情況娜搂,如果覺得需要進(jìn)行垃圾回收就會啟動垃圾收集器迁霎。

- (void)disableCollectorForPointer:(void *)ptr //調(diào)用這個函數(shù)之后,這個指針?biāo)赶虻膬?nèi)存不會被回收百宇。也就是說指針指向的對象會變成根集合中的對象欧引。如果想讓對象變?yōu)榭梢员辉俅位厥盏脑挘枰{(diào)用下面的enableCollectorForPointer:

- (void)enableCollectorForPointer:(void *)ptr //能夠讓通過disableCollectorForPointer:指定不允許被釋放的內(nèi)存或?qū)ο笤俅卧试S被釋放恳谎。

- (void)enable

- (void)disable //disable方法能讓垃圾收集器暫時停止內(nèi)存回收芝此。enable方法則能讓垃圾收集器恢復(fù)工作。但enable和disable不許成對使用因痛。這兩個函數(shù)一般被用于防止多線程中同時運行垃圾回收婚苹。

- (BOOL)isEnabled //用于判斷垃圾回收器是否有效,有效時返回真鸵膏。

實時API:

控制垃圾回收器的動作膊升。

void objc_startCollectorThread (void); //啟動一個線程專門運行垃圾收集器。

oid *objc_memmove_collectable(void *dst, const void *src, size_t size); //復(fù)制垃圾回收對象的內(nèi)存時使用該函數(shù)替代memcpy和memmove谭企。

內(nèi)存管理方式的比較:

首先讓我們來看看和手動內(nèi)存管理相比廓译,ARC和垃圾回收有哪些優(yōu)點评肆。

·不需要再在意對象的所有權(quán)

·可以刪除程序中內(nèi)存管理部分的大部分代碼,使程序看起來更清爽

·可以避免手動內(nèi)存管理時的錯誤(內(nèi)存泄漏等)

·不需要再在意引用計數(shù)內(nèi)存管理中的一些特殊用法非区。例如訪問方法的定義和臨時對象的使用等

·可以使多線程環(huán)境下的編程更簡單瓜挽。例如:不用擔(dān)心不同的線程之間可能出現(xiàn)的所有權(quán)沖突

垃圾回收的缺點如下所示。

·垃圾收集器運行時會影響程序的速度

·需要不停地監(jiān)視內(nèi)存的使用征绸,同引用計數(shù)的方法相比久橙,程序的速度會變慢

·會影響程序的效率。不經(jīng)常使用的內(nèi)存也會被垃圾收集器不時地訪問管怠,實際上有可能會占用

更多的內(nèi)存

·需要使用一些技巧來讓對象被回收或不被回收

·無法使用引用計數(shù)管理方式下的一些設(shè)計方針淆衷。例如:事先準(zhǔn)備好一些管理文件或其他資源類的對象,在對象被釋放的同時關(guān)閉資源

相比較而言渤弛,ARC沒有垃圾回收那么多缺點祝拯,但也有一些要注意的地方

·循環(huán)引用一旦形成就不會自己消失

·為了防止循環(huán)引用的形成,需要注意對象間的關(guān)系她肯。GUI的各個類之間也有可能形成循環(huán)引

用鹿驼,也要注意防止循環(huán)引用的形成

·理論上可被賦值的對象都可以被自動釋放,但在處理結(jié)構(gòu)體辕宏、數(shù)組畜晰、二重指針等類型的變量

時有一些限制

·需要注意Core Foundation的對象和Objectve-G的對象之間的轉(zhuǎn)換(詳情請參考附錄B)

更改內(nèi)存管理方式:

與對象的所有權(quán)和生存期相關(guān)的處理

釋放對象之后的善后處理

防止野指針的生成

有時還需要從對象之間的相互關(guān)系來重新考慮

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市瑞筐,隨后出現(xiàn)的幾起案子凄鼻,更是在濱河造成了極大的恐慌,老刑警劉巖聚假,帶你破解...
    沈念sama閱讀 222,104評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件块蚌,死亡現(xiàn)場離奇詭異,居然都是意外死亡膘格,警方通過查閱死者的電腦和手機(jī)峭范,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,816評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來瘪贱,“玉大人纱控,你說我怎么就攤上這事〔饲兀” “怎么了甜害?”我有些...
    開封第一講書人閱讀 168,697評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長球昨。 經(jīng)常有香客問我尔店,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,836評論 1 298
  • 正文 為了忘掉前任嚣州,我火速辦了婚禮鲫售,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘该肴。我一直安慰自己情竹,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 68,851評論 6 397
  • 文/花漫 我一把揭開白布沙庐。 她就那樣靜靜地躺著,像睡著了一般佳吞。 火紅的嫁衣襯著肌膚如雪拱雏。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,441評論 1 310
  • 那天底扳,我揣著相機(jī)與錄音铸抑,去河邊找鬼。 笑死衷模,一個胖子當(dāng)著我的面吹牛鹊汛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播阱冶,決...
    沈念sama閱讀 40,992評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼刁憋,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了木蹬?” 一聲冷哼從身側(cè)響起至耻,我...
    開封第一講書人閱讀 39,899評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎镊叁,沒想到半個月后尘颓,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,457評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡晦譬,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,529評論 3 341
  • 正文 我和宋清朗相戀三年疤苹,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片敛腌。...
    茶點故事閱讀 40,664評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡卧土,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出像樊,到底是詐尸還是另有隱情夸溶,我是刑警寧澤,帶...
    沈念sama閱讀 36,346評論 5 350
  • 正文 年R本政府宣布凶硅,位于F島的核電站缝裁,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜捷绑,卻給世界環(huán)境...
    茶點故事閱讀 42,025評論 3 334
  • 文/蒙蒙 一韩脑、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧粹污,春花似錦段多、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,511評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至鸭叙,卻和暖如春觉啊,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背沈贝。 一陣腳步聲響...
    開封第一講書人閱讀 33,611評論 1 272
  • 我被黑心中介騙來泰國打工杠人, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人宋下。 一個月前我還...
    沈念sama閱讀 49,081評論 3 377
  • 正文 我出身青樓嗡善,卻偏偏與公主長得像,于是被迫代替她去往敵國和親学歧。 傳聞我的和親對象是個殘疾皇子罩引,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,675評論 2 359

推薦閱讀更多精彩內(nèi)容

  • 1.什么是垃圾回收? 垃圾回收(Garbage Collection)是Java虛擬機(jī)(JVM)垃圾回收器提供...
    簡欲明心閱讀 89,565評論 17 311
  • 1. 垃圾回收的意義在C++中枝笨,對象所占的內(nèi)存在程序結(jié)束運行之前一直被占用蜒程,在明確釋放之前不能分配給其它對象;而在...
    愛情小傻蛋閱讀 935評論 0 11
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法伺帘,類相關(guān)的語法昭躺,內(nèi)部類的語法,繼承相關(guān)的語法伪嫁,異常的語法领炫,線程的語...
    子非魚_t_閱讀 31,664評論 18 399
  • 從三月份找實習(xí)到現(xiàn)在,面了一些公司张咳,掛了不少帝洪,但最終還是拿到小米、百度脚猾、阿里葱峡、京東、新浪龙助、CVTE砰奕、樂視家的研發(fā)崗...
    時芥藍(lán)閱讀 42,277評論 11 349
  • 那些平時發(fā)生在很多人身上的這樣那樣不順心的事情,都是因為在乎的太多胸哥,太注重自己的感受涯竟,結(jié)果反而會給自己招來更多的煩...
    白樺i閱讀 162評論 0 0