您好,登錄后才能下訂單哦!
Java中怎么實現內存回收,很多新手對此不是很清楚,為了幫助大家解決這個難題,下面小編將為大家詳細講解,有這方面需求的人可以來學習下,希望你能有所收獲。
各個線程共享的內存區域,用于儲蓄已被虛擬機加載的類信息、常量、靜態變量、即時編譯器編譯后的代碼等數據。 方法區有時也被稱為永久代。在 JDK1.8 及之后取消了永久代,取而代之的是元空間。在永久代中做調優是十分困難的,且效果不明顯。永久代的空間大小受制于 JVM 本身內存限制,而元空間是直接使用機器的內存,只受系統內存限制。元空間默認最大大小為無限制。 一些參數:
-XX:PermSize=N //方法區初始大小 -XX:MaxPermSize=N //方法區的最大大小 -XX:MetaspaceSize=N //元空間的初始大小 -XX:MaxMetaspaceSize=N //原空間的最大大小
堆是 Java 虛擬機所管理的內存中最大的一塊,是所有線程所共享的,此內存區域的唯一目的就是存放對象實例。堆是垃圾收集器管理的主要區域。在 HotSpot 中,大多數情況下內存被分為新生代和老年代,默認分配比例為 1:2。在新生代中又被分為一個 Eden 和兩個 Survivor ,分配比例為 8:1:1。新生代中對象的年齡在經歷一次 Minor GC 后年齡會+1,當年齡達到15(默認值)后會進入老年代。 一些參數:
-XX:InitialHeapSize=N //堆初始大小 -Xms1024m //簡寫值 -XX:MaxHeapSize=N //堆的最大值 -Xmx1024m //簡寫值 -XX:MaxTenuringThreshold=15 //新生代進入老年代的年齡
線程私有,用于存儲局部變量表、操作數棧、動態鏈接、方法出口等信息。包含程序計數器、虛擬機棧和本地方法棧。
哪些對象需要回收?
引用計數算法 給對象一個引用計數器,每當有一個地方引用它時,計數器就加 1,當引用失效時就減 1。任何計數器為 0 的對象都是不被使用的對象。 缺點:難以解決循環引用問題。
可達性分析算法 通過一系列的“GC Roots”作為起點,從這些節點開始向下搜索,搜索所達到的路徑稱為引用鏈。當一個對象不在任何引用鏈中,則此對象是不被使用的對象。
什么時候回收? 在 可達性分析算法 中從 GC Roots 搜索時,必須保證引用的一致性,以使對象的引用關系不再發生變化。這點就導致了 GC 必須停止所有的執行線程(Stop The World)。 在 HotSpot 中使用 OopMap 來記錄調用信息。在代碼中有 OopMap 記錄的地方稱為 SafePoint。當 GC 發生時,需要讓所有線程先跑到 SafePoint 再執行 GC 操作。
如何回收?
標記-清除算法 同名字一樣,這個方式分為“標記”和“清除”兩個階段,首先對不被使用的對象添加一個標記,之后對所有標記到的對象進行統一回收。 缺點:
標記和清除兩個階段的效率都不高
在回收之后會產生大量不連續的內存碎片,導致以后難以儲存較大的對象
復制算法 將對象分為兩塊,當一塊對象用完了,就將還在使用的對象復制到另一塊對象上去。較 標記-清除算法 有更高的效率 缺點:每次只能使用一塊內存,使內存的利用率變低了。
標記-整理算法 前半部分和 標記-清除算法 一樣,但后續將所有存活的對象移向一端,清除了內存碎片。
分代收集算法 根據對象的不同存活周期,一般把對象分為新生代和老年代,根據各個年代的特點采用不同的收集算法。 對于新生代,每次都有大量對象死去,故采用復制算法。 對于老年代,對象存活率高,采用 標記-清除 或 標記-整理 算法。
如果說收集算法是內存回收的方法論,那么垃圾收集器就是內存回收的具體實現。
Serial 一個最基本、發展歷史最悠久的收集器。采用單線程的收集方式,且在收集時必須暫停其他所有的工作線程,直到收集結束。在 Client 模式下有較好效果。
ParNew ParNew 收集器就是 Serial 的多線程版本,能與 CMS 配合工作。
Parallel Scavenge 吞吐量優先的收集器。(吞吐量=用戶代碼運行時間/(用戶代碼運行時間+垃圾收集時間))
Serial Old Serial 的老年代版本
Parallel Old Parallel Scavenge 的老年代版本,JDK1.7、JDK1.8 中以 Parallel Scavenge + Parallel Old 為默認的新生代、老年代回收器。
CMS 以最短回收停頓時間為目的,對 CPU 資源敏感
G1 JDK1.9 中的默認垃圾收集器,G1 的主要關注點在于達到可控的停頓時間,在這個基礎上盡可能提高吞吐量。G1 中每個塊也會充當 Eden、Survivor、Old 三種角色,但是它們不是固定的,這使得內存使用更加地靈活。
在 HotSpot 中,大多數情況下內存被分為新生代和老年代,默認分配比例為 1:2。在新生代中又被分為一個 Eden 和兩個 Survivor ,分配比例為 8:1:1。 一個新的對象一般會在新生代 Eden 區中分配。當 Eden 區沒有足夠空間進行分配時,將發起一次 Minor GC。 對于大對象(大量連續內存空間的Java對象),會直接進入老年代。 長期存活的對象(默認熬過 15 次 Minor GC),會進入老年代。 如果在 Survivor 中相同年齡的對象超過了 Survivor 的一般,這些對象將會直接進入老年代。
一些用于監視虛擬機狀態和故障處理的命令
命令 | 作用 |
---|---|
jps | 顯示系統內所有虛擬機進程 |
jstat | 用于收集虛擬機各方面運行數據 |
jinfo | 顯示虛擬機配置信息 |
jmap | 生成虛擬機內存轉儲快照(heapdump文件) |
jhat | 用于分析 heapdump 文件 |
jstack | 顯示虛擬機線程快照 |
看完上述內容是否對您有幫助呢?如果還想對相關知識有進一步的了解或閱讀更多相關文章,請關注億速云行業資訊頻道,感謝您對億速云的支持。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。