<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    磨刀不誤砍柴工

    合抱之木,生于毫末;九層之臺,起于累土;千里之行,始于足下。

       ::  ::  ::  :: 管理
    哪些內(nèi)存需要回收?
    什么時候回收?
    如何回收?
    一:哪些內(nèi)存需要回收?
    JAVA內(nèi)存中不需要考慮內(nèi)存回收問題的區(qū)域:
    程序計數(shù)器、虛擬機棧,本地方法棧
    (隨線程生滅,棧幀分配多少內(nèi)存在類結(jié)構(gòu)確定是就已知,因此它們的內(nèi)存分配與回收具備確定性。方法結(jié)束或線程結(jié)束時,內(nèi)存自然就跟著回收了)
    需要考慮內(nèi)存回收問題的區(qū)域:
    JAVA堆和方法區(qū)
    (創(chuàng)建哪些對象,創(chuàng)建多少對象,需要在運行期間才知道。不再用創(chuàng)建對象的類定義要從方法區(qū)回收)
    二:堆中對象的回收
    死去的對象才會被回收
    如何判斷對象已死
    a.引用計數(shù)算法:
    給對象添加一個引用計數(shù)器,每當(dāng)有一個地方引用它時,計數(shù)器值就加1。引用失效時,計數(shù)器值就減1.任何時候計數(shù)器為0的對象就是不可能再被使用的。
    優(yōu)點:引用計數(shù)算法實現(xiàn)簡單,判定效率也高。(使用在COM,FlashPlayer,Python等語言中)
    缺點:它很難解決對象之間相互循環(huán)引用的問題。(因此JAVA中沒有選用它來管理內(nèi)存)
    b.根搜索算法
    對于任何"GC Roots"都沒有路徑到達對象時,該對象就是不可用的。
    主流的程序語言都用的是根搜索算法,包括JAVA語言。
    哪些對象才是"GC Roots"
    • 虛擬機棧(棧幀中的本地變量表)中引用的對象
    • 方法區(qū)中的類靜態(tài)屬性引用的對象
    • 方法區(qū)中的常量引用的對象
    • 本地方法棧中JNI的引用的對象
    JAVA中的引用分為:強引用(Strong Reference)、軟引用(Soft Reference)、弱引用(Weak Reference)、虛引用(Phantom Reference)四種,強度依次減弱
    • 強引用:代碼中存在,類似 "Object obj = new Object()"這類。只要強引用存在,GC就永遠不會回收掉被引用的對象。
    • 軟引用:描述一些還有用,但非必需的對象。在系統(tǒng)將要發(fā)生內(nèi)存溢出異常之前,將把這些對象列進回范圍之中并進行第二次回收。如果這次回收還沒有足夠的內(nèi)存,才會拋出內(nèi)存溢出異常。通過 SoftReference類來實現(xiàn)軟引用。
    • 弱引用:也用于描述非必需對象,但它的強度要比軟引用更弱一些,被弱引用關(guān)聯(lián)的對象只能生成到下一次GC發(fā)生之前。當(dāng)GC工作時,無論當(dāng)前內(nèi)存是否足夠,都會回收弱引用關(guān)聯(lián)的對象。通過 WeakReference類來實現(xiàn)弱引用
    • 虛引用:也稱為幽靈引用或幻影引用。設(shè)置虛引用關(guān)聯(lián)的唯一目錄就是希望這個對象被回收時收到一個系統(tǒng)通知。通過PhantomReference來實現(xiàn)虛引用
    究竟什么樣的對象才會死掉呢?
    要真正宣告一個對象死亡,至少要經(jīng)歷兩次標(biāo)記過程:如果對象在進行根搜索后發(fā)現(xiàn)沒有與 GC Roots 相連接的引用鏈,那它將會被第一次標(biāo)記并放到“即將被回收的集合”中。
    與此同時進行一次篩選,篩選的條件是此對象是否有必要執(zhí)行 finalize() 方法。(當(dāng)對象沒有覆蓋 finalize()方法,或者 finalize() 方法已經(jīng)被虛擬機調(diào)用過,虛擬機將這兩種情況都視為 "沒有必要執(zhí)行"。)如果這個對象被判定為有必要執(zhí)行 finalize()方法,那么這個對象將會被放置到一個名為 F-Queue 的隊列之中,將在稍后由一條由虛擬機自動建立的,低優(yōu)先級的 Finalizer 線程去執(zhí)行(觸發(fā)finalize()方法而不等待)。finalize()方法是對象逃脫死亡命運的最后一次機會。對象要在finalize()方法中拯救自己,只要重新與引用鏈上任何一個對象建立關(guān)聯(lián)即可,這樣的話第二次標(biāo)記時它被移除出“即將回收的集合”。如果對象這個時候還沒有逃脫,那就真的離死不遠了。
    三:方法區(qū)的回收
    主要回收兩部份內(nèi)容:廢棄常量、無用的類
    常量回收與堆中對象回收類似。
    無用的類的判斷需同時滿足3條:
    • 該類所有的實例都已經(jīng)被回收,也就是說堆中不存在該類的任何實例
    • 加載該類的 ClassLoader 已經(jīng)被回收
    • 該類對應(yīng)的 java.lang.Class 對象沒有在任何地方被引用,無法在任何地方通過反射訪問該類的方法
    虛擬機對滿足上述3個條件的無用類進行回收。(只是可以,不會是必然回收)是否對類進行回收,HotSpot虛擬機了 -Xnoclassgc參數(shù)進行控制。還可以使用 -verbose:class 及-XX:+TraceClassLoading 和 -XX:+TraceClassUnLoading查看類的加載和卸載信息。
    四:垃圾收集算法
    4.1 標(biāo)記-清除算法
    標(biāo)記出所有需要回收的對象,標(biāo)記完成后統(tǒng)一回收掉所有被標(biāo)記的對象。(如何標(biāo)記在堆對象回收部分有介紹)
    它是最基礎(chǔ)的收集算法,后續(xù)收集算法都是基于這種思路改進而得到。
    缺點:效率不高,產(chǎn)生大量不連續(xù)的內(nèi)存碎片。
    (空間碎片太多,分配較大對象時就無法找到足夠連續(xù)內(nèi)存空間,而不得不提前觸發(fā)另一次垃圾收集動作)
    4.2 復(fù)制算法
    (為解決效率問題)
    將內(nèi)存按容量劃分為大小相等的兩塊,每次只使用其中的一塊。當(dāng)這一塊內(nèi)存用完了,就將還存活著的對象復(fù)制到另一塊上面,然后再把已使用過的內(nèi)存空間一次清理掉。
    優(yōu)點:內(nèi)存分配時不用考慮碎片的問題,實現(xiàn)簡單,運行高效
    缺點:內(nèi)存縮小為原來的一半。
    當(dāng)對象存活率較高時,需要較多的復(fù)制操作,效率將會變低。若不想浪費50%的空間,需要額外的空間進行分配擔(dān)保
    現(xiàn)在的商業(yè)虛擬機都采用這種收集算法來回收新生代(IBM研究表明,新生代對象98%是朝夕死的)。不過,并不是按1:1的比例來劃分內(nèi)存空間。而是將內(nèi)存分為一塊較大的 Eden 空間 和兩塊較小的Survivor空間。每次只使用 Eden 和其中的一塊Survivor。當(dāng)回收時,將Eden和Survivor中還存活著的對象一次性拷貝到另外一塊Survivor空間上,最后清理掉剛才的Eden和Survivor。默認(rèn)Eden和Survivor比例是 8:1。(98%是一般場景,另外一些場景下,當(dāng)Survivor空間不夠時,需依賴其它內(nèi)存【老年代】進行分配擔(dān)保)
    4.3 標(biāo)記-整理算法
    復(fù)制算法的缺點,決定老年代不能使用復(fù)制算法
    根據(jù)老年代特點,提出了“標(biāo)記-整理算法”。
    標(biāo)記過程仍然與“標(biāo)記-清除”算法一樣,但后續(xù)步驟不是直接對可回收對象進行清理,而是讓所有存活的對象都向一端移動,然后直接清理掉端邊界以外的內(nèi)存。
    4.4 分代收集算法
    當(dāng)前虛擬機的垃圾收集都采用“分代收集”算法。
    根據(jù)對象的存活周期將內(nèi)存劃分為幾塊。一般將堆分為新生代和老年代,這樣根據(jù)各個年代的特點采用最適當(dāng)?shù)氖占惴ā?/div>
    新生代采用復(fù)制算法
    老年代采用“標(biāo)記-清理”或“標(biāo)記-整理”算法
    五:垃圾收集器
    算法是內(nèi)存回收的方法論,垃圾收集器是內(nèi)存回收的具體實現(xiàn)。
    Serial收集器
    缺點:單線程收集器,垃圾收集時必須暫停其它所有的工作線程(Stop the world)。
    優(yōu)點:簡單而高效,對于Client模式下的虛擬機來說是一個很好的選擇。(也是Client模式下的默認(rèn)新生代收集器)
    ParNew 收集器
    其實就是 Serial 收集器的多線程版本
    是Server模式下的虛擬機的首選新生代收集器。(一個重要原因是,目前除了Serial收集器外,只有它能與CMS收集器配合工作)
    Paraller Scavenge 收集器
    并行的多線程收集器
    它的關(guān)注點與其它收集器的不同,它關(guān)注的是吞吐量
    吞吐量=運行用戶代碼時間/(運用用戶代碼時間+垃圾收集時間)
    Serial Old 收集器
    是Serial收集器的老年代版本,同樣是單線程收集器。使用“標(biāo)記-整理”算法
    Parallel Old 收集器
    是Parallel Scavenge收集器的老年代版本,使用多線和和“標(biāo)記-整理算法”,JDK1.6才提供。
    注重吞吐量及CPU資源敏感的場合,可以優(yōu)先考慮Parallel Scavenge加Parallel Old組合。
    CMS收集器 (Concurrent Mark Sweep)
    是一種以獲取最短回收停頓時間為目標(biāo)的收集器。
    對于B/S類重視服務(wù)器響應(yīng)速度,希望停頓時間最短類應(yīng)用就比較適合。
    基于“標(biāo)記-清除算法實現(xiàn)”
    內(nèi)存回收過程與用戶線程起并發(fā)的執(zhí)行。
    缺點:
    對CPU資源非常敏感。
    無法處理浮動垃圾
    收集結(jié)束時會產(chǎn)生大量空間碎片
    G1收集器(Garbage First)`
    JDK1.7正式發(fā)布時,很可能會有一個成熟的商業(yè)版本隨之發(fā)布。
    相對CMS的改進:
    基于“標(biāo)記-整理”算法實現(xiàn),不會產(chǎn)生空間碎片
    可以非常精確的控制停頓
    可以實現(xiàn)基本不犧牲吞吐量的前提下完成低停頓的內(nèi)存回收
    posted on 2013-10-09 21:35 liwei5891 閱讀(264) 評論(0)  編輯  收藏 所屬分類: Java

    只有注冊用戶登錄后才能發(fā)表評論。


    網(wǎng)站導(dǎo)航:
     
    主站蜘蛛池模板: 国产精品小视频免费无限app| 黄色片网站在线免费观看| 99在线免费观看| 久久久久亚洲AV无码专区桃色| 亚洲AV无码男人的天堂| 一个人免费观看在线视频www| 国产99在线|亚洲| 性xxxx视频播放免费| 亚洲国产成人久久综合| 国产在线ts人妖免费视频| 美女被羞羞网站免费下载| 亚洲国产综合精品中文字幕| 国产免费A∨在线播放| 亚洲乱码中文字幕久久孕妇黑人| 最近国语视频在线观看免费播放 | 久久久久久夜精品精品免费啦| 亚洲精品夜夜夜妓女网| 四虎影视成人永久免费观看视频| 亚洲视频在线观看| 在线看片v免费观看视频777| 亚洲最大福利视频| 国产L精品国产亚洲区久久| 人人玩人人添人人澡免费| 亚洲福利一区二区三区| 精品剧情v国产在免费线观看 | 57PAO成人国产永久免费视频 | 免费无码肉片在线观看| 欧美激情综合亚洲一二区| 日本亚洲国产一区二区三区| 久久免费国产视频| 亚洲精品无码专区在线| 久久精品国产精品亚洲| 国产精品视频免费观看| 美女视频黄频a免费观看| 亚洲电影中文字幕| 免费无码又爽又高潮视频 | 国产亚洲高清不卡在线观看| 亚洲高清中文字幕免费| 天堂亚洲免费视频| 亚洲黄色片在线观看| 亚洲?v女人的天堂在线观看|