JVM-內存模型

JVM內存模型
image.png

程序計數器: 較小的內存空間, 線程所執行的字節碼的行號指示器,線程私有,不會拋出內存溢出異常
虛擬機棧: 方法在執行的同時都會創建一個棧幀(棧楨大小缺省爲1M,可用參數 –Xss調整大小,例如-Xss256k),進行壓棧,執行完彈棧。線程私有,會有兩種異常, StackOverflowError, OutOfMemoryError
本地方法棧:和虛擬機棧相似, 不同的是本地方法棧爲Native方法服務。
堆: 存放對象實例, 可細分爲新生代和老年代,再細分可分爲Eden空間、From Survivor空間、To Survivor空間。線程共享,拋出OutOfMemoryError -Xms:堆的最小值;-Xmx:堆的最大值;-Xmn:新生代的大小;-XX:NewSize;新生代最小值;-XX:MaxNewSize:新生代最大值;方法區: 存儲已被虛擬機加載的類信息、常量、靜態變量,線程共享, 拋出OutOfMemoryError
jdk1.7及以前:-XX:PermSize;-XX:MaxPermSize;
jdk1.8以後:-XX:MetaspaceSize; -XX:MaxMetaspaceSize
jdk1.8以後大小就只受本機總內存的限制
如:-XX:MaxMetaspaceSize=3M運行時常量池:方法區的一部分

不同版本jdk內存區域的變化
image.png
jdk1.6運行時常量池在方法區中
jdk1.7運行時常量池在堆中
jdk1.8多出個元空間的概念,

棧上分配
虛擬機提供的一種優化技術,基本思想是,對於線程私有的對象,將它打散分配在棧上,而不分配在堆上,好處是對象跟着方法調用自行銷燬,不需要進行垃圾回收,可以提高性能-server JVM運行的模式之一, server模式才能進行逃逸分析-XX:+DoEscapeAnalysis:啓用逃逸分析(默認打開)-XX:+PrintGC:打印GC日誌-XX:+EliminateAllocations:標量替換(默認打開)-XX:-UseTLAB 關閉本地線程分配緩衝

對象的分配
1.類加載
2.分配內存:指針碰撞和空閒列表,爲了併發安全,CAS和TLAB解決,TLAB是爲每一個線程分配一塊私有的區域。
3.對內存裏的變量進行初始化,int爲0,boolean默認false等
4.設置對象的信息到對象頭,包括類的元數據信息,對象的哈希碼,對象的GC分代年齡等
5.剛剛開始初始化對象的

內存佈局
在HotSpot虛擬機中,對象在內存中存儲的佈局可以分爲3塊區域:對象頭(Header)、實例數據(Instance Data)和對齊填充(Padding)。對象頭包括兩部分信息,第一部分用於存儲對象自身的運行時數據,如哈希碼(HashCode)、GC分代年齡、鎖狀態標誌、線程持有的鎖、偏向線程ID、偏向時間戳等。 對象頭的另外一部分是類型指針,即對象指向它的類元數據的指針,虛擬機通過這個指針來確定這個對象是哪個類的實例。第三部分對齊填充並不是必然存在的,也沒有特別的含義,它僅僅起着佔位符的作用。由於HotSpot VM的自動內存管理系統要求對對象的大小必須是8字節的整數倍。當對象其他數據部分沒有對齊時,就需要通過對齊填充來補全。

堆溢出
參數 : -Xms5m -Xmx5m -XX:+PrintGC
出現java.lang.OutOfMemoryError: GC overhead limit exceeded 一般是(某個循環裏可能性最大)在不停的分配對象,但是分配的太多,把堆撐爆了。
出現java.lang.OutOfMemoryError: Java heap space一般是分配了巨型對象

棧溢出
參數:-Xss256k
java.lang.StackOverflowError 一般的方法調用是很難出現的,如果出現了要考慮是否有無限遞歸。
虛擬機棧帶給我們的啓示:方法的執行因爲要打包成棧楨,所以天生要比實現同樣功能的循環慢,所以樹的遍歷算法中:遞歸和非遞歸(循環來實現)都有存在的意義。遞歸代碼簡潔,非遞歸代碼複雜但是速度較快。

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