JVM記憶體管理--電腦記憶體和Java記憶體組件
JVM一向很好的幫我們管理記憶體,它就是一個賢內助:“向政府(記憶體空間)能要到地盤,還能有效對自己的一畝三分地進行管理。”但是有時候呢,我們不懂憐香惜玉的一而再再而三的向它施壓,把我們的一切不管好的壞的都扔給它,但是呢它也沒有怨言,只是在地實在放不下的時候會悄悄的告知我們:“StackOverFlowError或者OutOfMemoryError。”既然它如此勞心勞力的付出,我們是不是也應該知道為什麼它要拋出來這些異常呢。又或者我們通過一些方式避免掉這些異常讓我們的JVM更歡快的奔跑在它的一畝三分地上呢。
那在這之前,或許我們應該瞭解下它所處一畝三分地周圍的環境。
寄存器用於儲存計算單元執行指令的中間結果,寄存器大小決定了一次計算的可使用的最大值,串連RAM和處理器或者寄存器和處理器的叫做地址匯流排,地址匯流排決定了處理器最大的定址空間,32位匯流排寬度可以擁有2的32次方個記憶體位置,所以32位匯流排可以擁有4G的記憶體空間。
每個程式啟動並執行時候會向系統申請一段獨立的記憶體空間,但隨著程式的龐大和任務的複雜性,實體記憶體無法滿足需求,此時就有了虛擬記憶體,虛擬記憶體可以使多個進程在同時運行時可以共用實體記憶體,這裡的共用只是空間上的共用,邏輯上它們依然獨立,當然虛擬記憶體還可以擴充記憶體空間。
系統會將不經常活動的程式的資料移到一個磁碟檔案中,將真正的實體記憶體留給真正啟動並執行程式用,但當喚醒這個程式時,os又會將磁碟上資料重新交換到實體記憶體上,此時磁碟會吱吱的響,但我們要避免這種情況的出現,效率會很低,在linux伺服器上我們經常關注swap分區,swap分區如果被經常使用,系統就會非常緩慢,表示系統記憶體嚴重不足,或者某些程式沒有即時釋放記憶體。
那麼我們可以看出實體記憶體對於程式來說十分重要,而實體記憶體又會分為核心空間和使用者空間,核心空間保證操作程式的調度和硬體的邏輯串連,我們的程式自然而然的使用的是使用者空間,所以每一次調用都會存在兩塊空間的切換,比如一次網路傳輸,核心空間先接收遠程主機傳來的資料,再從核心空間複製到使用者空間供程式使用,這種情況雖然保證了安全,但是效率很低,當然現在有很多種方式來提升效率減少複製。
那麼正題來了,在我們的Java組件中是如何使用記憶體呢。 一.堆
眾所周知,堆是用來儲存Java對象的地方,它的大小在JVM啟動時就一次性的向系統申請完成,-Xmx表示堆的最大大小,-Xms表示初始化大小。一旦申請完成,堆的大小就固定,不能在記憶體不夠時再向系統申請,當然同理記憶體閒置時候它也不會將記憶體還回去,就是自成世界了,另立門戶了,生死由己。 二.線程
在用一段簡單代碼看JVM的執行過程 這篇文章中我們知道每個線程建立時都會建立一個私人的棧來儲存資料,在HotSpot這款JVM中不區分虛擬機器棧和本地方法棧,棧容量大小通過-Xss設定。 三.類和載入器
類和類載入器也被儲存在堆中,這個地區叫永久代(PermGen區)。
注意的是:一個jar包的類用哪個JVM就載入那一個,不會一股腦的全載入完,理論上使用的類越多,Java使用的類越多,需要佔用的記憶體也越多。 四.NIO
NIO使用的記憶體是本機記憶體而不是Java堆上的記憶體,另外NIO的ByteBuffer產生的資料和網路或者磁碟互動的時候都在作業系統的核心空間發生,不需要複製到本機記憶體,如果我們需要發送很小的資料效率會比較高。
我們JVM運行時要處理的資料主要關注點在運行時資料區,在下一章,我將繼續學習Java記憶體配置結構和Java記憶體配置策略
文章轉自:https://blog.csdn.net/sureSand/article/details/78715056