JVM內存(堆和非堆)jdk1.8

前言

1.8同1.7比,最大的差別就是:元數據區取代了永久代。元空間的本質和永久代類似,都是對JVM規範中方法區的實現。不過元空間與永久代之間最大的區別在於:元數據空間並不在虛擬機中,而是使用本地內存。

調試工具

arthas調試工具
https://alibaba.github.io/arthas/dashboard.html

查看堆內存
jmap -heap PID

查看一個進程有哪些內存映射
pmap -x PID

堆和非堆內存簡介

堆和非堆均是在java虛擬機啓動時創建。
Java 虛擬機具有一個堆(Heap),堆是運行時數據區域,所有類實例和數組的內存均從此處分配。JVM8中把運行時常量池、靜態變量也移到堆區進行存儲。對象的堆內存由稱爲垃圾回收器的自動內存管理系統回收。

在JVM中堆之外的內存稱爲非堆內存(Non-heap memory)。由所有線程共享的方法區。方法區屬於非堆內存。它存儲每個類結構,如運行時常數池、字段和方法數據,以及方法和構造方法的代碼。

基本概念

(堆)Heap分爲3個區,Young即新生代(分爲Eden區、From Survivor、To Survivor三個區域,默認比例是8:1:1),Old即老生代。
Young保存剛實例化的對象。當該區被填滿時,GC會將對象移到Old區。Permanent區則負責保存反射對象。
(非堆)MetaSpace:全稱是MetaSpace,即方法區。用於存放Class和Meta信息,Class在被Load的時候被放入該區域。

堆內存分配

類型 默認值
初始分配的堆內存-Xms 物理內存的1/64
最大分配的堆內存-Xmx 物理內存的1/4
-XX:PermSize設置非堆內存初始值(jdk1.7) 物理內存的1/64
XX:MaxPermSize設置最大非堆內存(jdk1.7) 物理內存的1/4
-XX:MetaspaceSize初始元空間大小(jdk1.8) 21M
-XX:MaxMetaspaceSize最大元空間大小(jdk1.8) 沒有限制

在這裏插入圖片描述

linux內存與jvm內存聯繫

我們經常會碰到這樣一種情況,使用dashboard或者jmap查看到heap+noheap內存與top看到的內存大小不同。
RES(Resident Set Size)是常駐內存的意思,進程實際使用的物理內存
在這裏插入圖片描述
在這裏插入圖片描述
通過上圖我們可以看到,RES佔用了1.8g,heap+noheap佔用了1.3g那麼其餘的0.6G內存去哪了呢?

當Java程序啓動後,會根據Xmx爲堆預申請一塊保留內存,並不會直接使用,也不會佔用物理內存
然後申請(malloc之類的方法)Xms大小的虛擬內存,但是由於操作系統的內存管理是惰性的,有一個內存延遲分配的概念。malloc雖然會分配內存地址空間,但是並沒有映射到實際的物理內存,只有當對該地址空間賦值時,纔會真正的佔用物理內存,纔會影響RES的大小。

所以可能會出現進程所用內存大於當前堆+非堆的情況

比如說該Java程序在5分鐘前,有一定活動,佔用了1.8G堆內存(無論堆中的什麼代),經過GC之後,雖然堆內存已經被回收了,堆佔用很低,但GC的回收只是針對Jvm申請的這塊內存區域,並不會調用操作系統釋放內存。所以該進程的內存並不會釋放,這時就會出現進程內存遠遠大於堆+非堆的情況。

至於Oracle文檔上說的,Jvm可能會向操作系統釋放內存,經過測試沒有發現釋放的情況。不過就算有主動釋放的情況,也不太需要我們程序關心了。

參考文章:
JVM 老年代內存沒辦法回收了
https://blog.csdn.net/david_lua/article/details/102735551?utm_medium=distribute.pc_relevant.none-task-blog-baidujs-4

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章