欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

詳解Java內存管理中的JVM垃圾回收

 更新時間:2018年08月27日 09:06:21   作者:且聆聽風  
這篇文章給大家分享了關于Java內存管理中的JVM垃圾回收的相關知識點內容,有興趣的朋友們可以學習參考下。

一.概述

相比起C和C++的自己回收內存,JAVA要方便得多,因為JVM會為我們自動分配內存以及回收內存。

在之前的JVM 之內存管理 中,我們介紹了JVM內存管理的幾個區(qū)域,其中程序計數(shù)器以及虛擬機棧是線程私有的,隨線程而滅,故而它是不用考慮垃圾回收的,因為線程結束其內存空間即釋放。

而JAVA堆和方法區(qū)則不一樣,JAVA堆和方法區(qū)時存放的是對象的實例信息以及對象的其他信息,這部分是垃圾回收的主要地點。

二.JAVA堆垃圾回收

垃圾回收主要考慮的問題有兩個:一個是效率問題,一個是空間碎片問題。

而Java堆中的垃圾回收可以分為兩個區(qū)域,一個是新生代,一個是老年代。其中新生代又分為一塊比較大的Eden空間和兩塊較小的Survivor空間。因為新生代和老年代所存儲的對象群體是不一樣的,為了在效率和空間碎片問題中取得平衡,新生代和老年代所使用的垃圾回收算法是不一樣。

新生代 -復制算法

從名字上就知道,新生代主要存放的是比較新的對象,回收多次之后仍然存活的對象,就會被送到老年代中區(qū)。由此可知新生代的垃圾回收是比較頻繁的,所以為解決效率問題,新生代使用了復制算法。復制算法可以將內存分為大小相等的兩塊,每次分配時使用其中一塊,當這一塊用完時,就將還存活的對象復制到另一塊內存上面區(qū)。此時已使用過的這一塊內存就可以一次清理掉,這樣也不用擔心內存碎片的問題。當然這種算法的一個缺點就是內存使用率比較低,只有一半(每次只能一半用來分配出去)。

而IBM公司的研究表明,新生代中的對象98%都是”照生夕死“,所以不需要按照1:1劃分,故而會將內存分為一塊較大的Eden空間和兩塊小的Survivor空間。

那么為什么會有兩塊Survivor呢,復制算法不是只需要一塊Eden和一塊Survivor就夠了嗎?

其實這主要還是為了解決碎片化的問題。假設只有一個Survivor區(qū),當Eden區(qū)滿的時候,進行Gc,存活對象被分配到了Survivor區(qū),清空Eden區(qū)。當再一次Gc完成后,存活的對象繼續(xù)放在Survivor區(qū),這樣不是很美好嗎,不會有內存碎片啊!但是別忘了,第一次存到Survivor區(qū)的對象很可能在第二次Gc的時候就失活了,清理掉Survivor失活對象不就會產生內存碎片了嗎?

所以Java堆使用了兩個Survivor區(qū),一個from Survivro和一個toSurvivor,第一次Eden滿的時候,復制算法將存活對象放到from Survivor區(qū),清空Eden。第二次,Eden滿時,將Eden和from Survivor區(qū)存活的對象放到to Survivor區(qū),清空Eden和from Survivor,然后重要的一步,將from Survivor和to Survivor角色互換!這樣就解決了內存碎片化的問題。

老年代 -標記/整理算法

首先要明白老年代存放的都是會存活得比較久的對象,所以如果老年代也使用復制算法的話,那么復制對象的開銷時比較大的,因為老年代的對象基本上都會存活。

標記/整理算法很好理解,主要也就是”標記“,”整理“兩個步驟,先將要回收的對象標記,然后讓存活對象向著一端移動,最后將邊界以外的內存,然后Gc完成。

三.方法區(qū)垃圾回收

在某些地方的解釋中,方法區(qū)也會被叫做“永久代”,與JAVA堆不同,這里存放的是類的信息以及一些常量信息,故而這個區(qū)域中被分配的內存一般比較難以被回收,所以才有有”永久代“之名。

雖然方法區(qū)中垃圾回收效率較低,但被分配的內存卻也并非真的就永不被回收,其主要回收的有兩部分內容:廢棄常量和無用的類。廢棄常量的回收與JAVA堆中類實例回收類似,當常量池中一個常量沒有被引用時,就有可能被回收。比如常量池中有一個字符串常量“abc”,當沒有任何一個String對象值為"abc"時,那么下一次垃圾回收"abc"常量就有可能會被回收。

而對于無用的類的回收,首先需要判斷什么樣的類才是”無用的類“:

  • 該類所有的實例都已被回收,即JAVA堆中沒有該類的實例。
  • 加載類的ClassLoader已經被回收。
  • 該類對應的java.lang.Class對象沒有在任何地方被引用,無法在任何地方通過反射訪問該類的方法。

虛擬機可能會堆滿足這三個條件的”無用的類“進行回收,僅僅是可能,并非必然。

相關文章

  • java適配器模式如何讓不兼容的接口變得兼容

    java適配器模式如何讓不兼容的接口變得兼容

    這篇文章主要為大家介紹了java適配器模式如何讓不兼容的接口變得兼容示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-09-09
  • 解決spring-data-jpa mysql建表編碼問題

    解決spring-data-jpa mysql建表編碼問題

    這篇文章主要介紹了解決spring-data-jpa mysql建表編碼問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • Java線程狀態(tài)轉換關系實例解析

    Java線程狀態(tài)轉換關系實例解析

    這篇文章主要介紹了Java線程狀態(tài)轉換關系實例解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-08-08
  • java9區(qū)分opens與exports

    java9區(qū)分opens與exports

    本篇文章主要給大家講述了java9中opens與exports的區(qū)別以及用法的不同之處,一起學習下吧。
    2018-02-02
  • springboot配置文件綁定實現(xiàn)解析

    springboot配置文件綁定實現(xiàn)解析

    這篇文章主要介紹了springboot配置文件綁定實現(xiàn)解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-01-01
  • spring boot創(chuàng)建和數(shù)據(jù)庫關聯(lián)模塊詳解

    spring boot創(chuàng)建和數(shù)據(jù)庫關聯(lián)模塊詳解

    這篇文章主要給大家介紹了關于spring boot創(chuàng)建和數(shù)據(jù)庫關聯(lián)模塊的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-10-10
  • 解決Netty解碼http請求獲取URL亂碼問題

    解決Netty解碼http請求獲取URL亂碼問題

    這篇文章主要介紹了解決Netty解碼http請求獲取URL亂碼問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-06-06
  • Java如何通過jstack命令查詢日志

    Java如何通過jstack命令查詢日志

    在分析線上問題時常使用到jstack?<PID>命令將當時Java應用程序的線程堆棧dump出來,面對jstack?日志,我們如何查看?下面小編給大家介紹下Java如何通過jstack命令查詢日志,感興趣的朋友一起看看吧
    2023-03-03
  • Spring數(shù)據(jù)源及配置文件數(shù)據(jù)加密實現(xiàn)過程詳解

    Spring數(shù)據(jù)源及配置文件數(shù)據(jù)加密實現(xiàn)過程詳解

    這篇文章主要介紹了Spring數(shù)據(jù)源及配置文件數(shù)據(jù)加密實現(xiàn)過程詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-05-05
  • 基于MapperXML掃描的問題

    基于MapperXML掃描的問題

    這篇文章主要介紹了MapperXML掃描的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-10-10

最新評論