从javaScript数据类型开始了解垃圾回收机制
一、 javaScript數(shù)據(jù)類型
javaScript 數(shù)據(jù)類型分為:基本數(shù)據(jù)類型、引用數(shù)據(jù)類型
基本數(shù)據(jù)類型
分類:Number、String、Boolean、Null、Undefined、Symbol。
存儲地址:棧。
引用數(shù)據(jù)類型
分類:Object、Array、Function。
存儲地址:堆。
二、存儲地址
棧
特點:小、速度快、有序。
通常情況下,棧的內(nèi)存空間不會設(shè)置很大(因為棧空間是用來存放執(zhí)行上下文的,如果棧空間設(shè)置的很大,會影響切換執(zhí)行上下文的速度),棧一般用于存儲一些 原始類型 的小數(shù)據(jù)。
堆
特點:大、速度慢、無序。
堆的內(nèi)存空間很大,常用于存儲類似 引用類型 的這樣的大數(shù)據(jù)。
三、垃圾回收機制
棧內(nèi)存如何回收
當(dāng)函數(shù)在執(zhí)行時,有一個記錄當(dāng)前執(zhí)行狀態(tài)的指針(ESP)指向它。
當(dāng)此函數(shù)被執(zhí)行結(jié)束后,ESP指針指向下一個執(zhí)行函數(shù)。雖然此時上一個函數(shù)還存在于占內(nèi)存中,但下一個函數(shù)的執(zhí)行可能會覆蓋掉它。
堆內(nèi)存如何回收
這里主要介紹:V8引擎的垃圾回收機制。
原理:
1、內(nèi)存劃分
引擎將堆內(nèi)存分為兩個部分:新生代、老生代
新生代:存放生存時間較短的對象 -------由副垃圾回收器回收。
老生代:存放生存時間較長的對象 -------由主垃圾回收器回收。
2、副垃圾回收器
副垃圾回收器將 新生代內(nèi)存空間 分為兩個部分:對象區(qū)域 和 空閑區(qū)域。
新加入的對象都會被放入對象區(qū)域,當(dāng)對象區(qū)域快滿的時候,執(zhí)行一次回收。
注意:如果對象區(qū)域很大,每次清理的時間就會很長,所以對象區(qū)域一般都很小,但也很容易被放滿。所以經(jīng)過兩次垃圾回收之后依然存活的對象會被放入老生代。
回收過程:副垃圾回收器對 對象 區(qū)域中的垃圾進行標(biāo)記,標(biāo)記完成之后,進入垃圾清理階段,并將活躍的對象移入空閑區(qū)域(這時候會出現(xiàn)許多內(nèi)存不連續(xù)的空白區(qū)域),同時還會把他們有序的排列起來,這個排列的過程就相當(dāng)于做了內(nèi)存整理。執(zhí)行完上述操作后,再將 對象區(qū)域 與 空閑區(qū)域 的的角色相調(diào)換。
3、主垃圾回收器
主要采用 標(biāo)記清除法 進行垃圾回收。
標(biāo)記:
從一組根元素開始,遞歸遍歷這組根元素,在遍歷過程中能夠被遍歷到的元素成為活動對象,沒有被遍歷到的元素則是垃圾數(shù)據(jù)。
清除:
問題1:因為主垃圾回收器主要用來回收內(nèi)存區(qū)域大,存儲數(shù)據(jù)大的垃圾,所以如果對所有的垃圾數(shù)據(jù)依次清除,會帶來很多的內(nèi)存碎片。
解決:標(biāo)記整理(在標(biāo)記的過程中,將所有活躍的對象都向一邊移動,最后清除掉邊界以外的垃圾)。
問題2:JavaScript 是運行在主線程之上的,一旦執(zhí)行垃圾回收算法,都需要將正在執(zhí)行的 JavaScript 腳本暫停下來,待垃圾回收完畢后再恢復(fù)腳本執(zhí)行,非常的耗時。
解決:讓垃圾回收操作和js腳本交替執(zhí)行(類似時間片)。
思考:閉包之所以會帶來內(nèi)存泄漏的問題,主要是因為不能對其變量進行垃圾回收,如何解決這個問題呢?
答案:使用完內(nèi)存變量后,將此變量指向null。
總結(jié)
以上是生活随笔為你收集整理的从javaScript数据类型开始了解垃圾回收机制的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java高级特性——反射
- 下一篇: Cause: java.lang.Ill