當前位置:
首頁 > 知識 > Java內存分配及垃圾回收機制

Java內存分配及垃圾回收機制


Java內存區域

1、內存區域jvm運行時數據區域 程序計數器 Java虛擬機棧 本地方法棧 方法區

Java堆

大圖

Java內存分配及垃圾回收機制

2、概念解釋
  • 程序計數器 線程私有的一塊很小的內存空間,它是當前線程所執行的位元組碼的行號指示器。位元組碼解釋器工作時就是通過改變這個計數器的值來選取下一條需要執行的位元組碼指令,分支、循環、跳轉、異常處理、線程恢復等基礎功能都需要依賴這個計數器來完成。每個線程都對應一個獨立的程序計數器, 記錄著線程執行指令,保障了線程間的切換後能恢復到正確的執行位置,從而保障了Java虛擬機多線程能有條不紊地輪流切換執行。

  • Java虛擬機棧

    線程私有, 它的生命周期與線程相同。虛擬機棧描述的是Java方法執行的內存模型:每個方法被執行的時候都會同時創建一個棧幀用於存儲局部變數表、操作棧、動態鏈接、方法出口等信息。每一個方法被調用直至執行完成的過程,就對應著一個棧幀在虛擬機棧中從入棧到出棧的過程。

  • 本地方法棧

    為虛擬機使用到的native方法服務, 其作用類似於Java虛擬機棧, 只不過虛擬機棧為虛擬機執行Java方法(也就是位元組碼)服務。

  • 方法區 各個線程共享的內存區域, 用於存儲已被虛擬機載入的類信息、常量、靜態變數、即時編譯器編譯後的代碼等數據。方法區也是我們通常所說的永久區,它的大小可通過參數-XX:PermSize、-XX:MaxPermSize進行設置

  • Java堆

    Java堆是Java虛擬機所管理的內存中最大的一塊, 被所有線程共享的一塊內存區域, 在虛擬機啟動時創建,是存儲Java對象實例的地方。Java堆細分為:新生代和老年代,而新生代又可細分為Eden空間、from survivor空間、to survivor空間等。

    根據JVM規範,Java堆可以處於物理上不連續的內存空間中。只要邏輯上是連續的即可。可通過-Xmx設置最大Java堆的大小,-Xms設置初始化時Java堆大小。

3、為了更好理解堆、棧、方法區, 以下舉個栗子

來,先看下一段代碼

import java.text.SimpleDateFormat;
import java.util.Date;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* mvp
* @author yuanmeng
* @create 2017-06-18 下午8:44
**/
public class MVP {

private static Logger LOG = LoggerFactory.getLogger(MVP.class);

public void winMVP(String name) {

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
String today = sdf.format(new Date);

LOG.info("威少 mvp");
}
}

這段程序的數據信息在內存中存放如下圖所示:

Java內存分配及垃圾回收機制


垃圾收集器

1)檢測垃圾機制

Java運行時所載入的數據, 如類信息、實例對象信息等會佔用系統內存, 所幸的是Java有個強大的垃圾收集器, 在內存不夠分配對象的時候會觸發GC。

檢測垃圾的方法常見的有兩種:1. 引用計數法;2. 可達性分析演算法。

  • 引用計數法

    給對象附加一個引用計數器,只要有一個地方引用它,計數器值加1。當引用失效時就減1。任何時刻計數器都為0的對象就是不可能再被使用的,將其判定為可回收的對象。這種檢測機制的優點是很簡單, 但它有個很致命的缺點,它無法解決對象間循環引用問題。如hashMap在高並發的時候會出現循環鏈表問題。

  • 可達性分析演算法

    主流的JVM基本都使用可達性分析演算法來判斷對象是否存活,通過一系列「GC Roots」的對象作為起始點向下搜索,搜索所走過的路徑為引用鏈,當一個對象沒有任何引用鏈與GC Roots相連,代表該對象不再被使用,將其判定為可回收的對象。

看下圖,Object5 、Object6、Object7是從跟節點出發無法可達到的對象, 可判定為回收對象。

Java內存分配及垃圾回收機制

2)回收垃圾機制

標記-清除演算法

先標記待回收的對象,然後再對標記的對象進行清除。圖解

Java內存分配及垃圾回收機制

這種演算法缺點 :

  • 標記和清除兩個過程, 效率不高
  • 標記清除後會產生大量不連續內存碎片, 多次進行標記和清除回收後可能會導致以後程序在運行過程中需要分配大對象時,無法找到足夠的連續內存而不得不提前出發GC,而GC需要耗時間。

複製演算法

複製演算法是將內存分成兩塊,一塊存儲程序運行分配的對象,一塊是空閑區域。當存儲對象的內存區域用完了,會將此區域存活的對象複製到另一塊空閑區域,然後再把已使用的內存空間一次清理掉。

Java內存分配及垃圾回收機制

複製演算法實現簡單、高效。但代價有點大了,可用內存縮小為原來的一半,以「空間換取時間」。

  • 標記-整理演算法

標記-整理演算法是對原有標記-清除演算法進行的改造,不是直接對可回收對象進行清理,而是讓所有存活對象都向另一端移動,然後直接清理掉端邊界以外的內存。

Java內存分配及垃圾回收機制

  • 分生代演算法

前面也介紹過了,Java堆內存可以細分為新生代、老年代。新生代生存的生命周期比較短,每次經過GC後仍存活的對象年齡會加1, 多次GC後仍存活的對象會直接晉陞為老年代。而老年代的生命周期比較長。換句話說,每次GC後新生代生存下來的對象很少,老年代存活對象多。前面分析過,生存對象少的新生代更適合用複製演算法,生存對象多的老年代適合用標記-清除或者標記-整理演算法


參考文獻

《深入理解Java虛擬機》


寫在最後

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 科技優家 的精彩文章:

OpenCV 之 神經網路(一)
ecshop的aes加密
JavaScript HTML DOM 元素
把angular項目整合到.net mvc中
來吧學學.Net Core之項目文件簡介及配置文件與IOC的使用

TAG:科技優家 |

您可能感興趣

JVM內存分配、GC原理與垃圾收集器
Python 和 Ruby 的分代垃圾回收機制
很多Gmail用戶都收到了垃圾郵件
iMessage垃圾信息泛濫 群發低至7分錢/條
它能完美解決全家垃圾的收集,Townew拓牛智能垃圾桶使用分享
CMS垃圾收集器
微軟 Visual Studio C+Runtime 安裝程序是失效的、垃圾的
垃圾女孩有一本Junk Journal
國內iPhone用戶正在面臨大量iMessage垃圾
警惕!國內iPhone用戶正在面臨大量iMessage垃圾信息
利用WhatsApp漏洞傳播垃圾郵件和假消息
GNOME Shell內存泄露問題正在修復中 原因竟是忘記進行垃圾回收
沃爾沃推出新型全電動「垃圾運輸」車;Google Research 升級為 Google AI
蘋果有意使用AI來攔截iMessage垃圾信息
垃圾郵件活動濫用SettingContent-ms傳播FlawedAmmyy RAT
為什麼Holochain是垃圾
Apple 正在努力減少中國的 iMessage 垃圾郵件
Windows 10將整合清理垃圾文件功能
iPhone垃圾信息被罵慘了,蘋果一拍腦門:上機器學習呀
Anitama新聲:現實這個自動存檔的垃圾遊戲