天天看點

Jvm建立對象之記憶體配置設定-JVM(七)

上篇文章介紹了jvm建立,會校驗是否已加載類,沒有則加載,通過之前學的源碼,classLoader加載完之後,虛拟機開始給類配置設定記憶體,指針移動配置設定和free連結清單配置設定,解決并發配置設定情況用cap和TLAB方法。之後設定對象頭部資訊,有mark word線程鎖,分代年齡等,klass pointer。還有指針壓縮的概念。

一、指針壓縮的好處?

1、在64位平台的HotSpot使用,則會記憶體多使用一倍,占用較大帶寬,gc也會壓力增大。

2、堆記憶體小于4g(2^32)的時候會自動指針壓縮。

3、堆記憶體大于32g的時候會指針壓縮無效。

-XX:+UseCompressedClassPointer隻會壓縮klassPointer指針

二、逃逸分析

當我們一個方法裡面建立一個新的對象,如果這個對象return,則會在方法外部被調用,如果沒有return,則隻會在方法内部調用,這種則就稱為方法逃逸。

第二種隻在方法内調用,可以把他配置設定在棧記憶體裡面,随着棧記憶體的回收一起被gc。

預設是開啟逃逸分析,如果關閉則使用

-XX:-DoEscapeAnalysis

三、标量替換,聚合量

當一個對象通過逃逸分析确定不會逃逸,也就是不會被外部調用時候,這時候jvm不會建立該對象,而是将該對象分解若幹個方法使用成員變量替換,這樣就不會因為一大塊連續的記憶體空間而導緻不夠用。

Jdk1.7之後預設開啟标量替換,關閉則使用

-XX:+EliminateAllocations

(标量就是不可拆分的量,比如int,long)标量對立就是可以被進一步分解的量,叫聚合量,可以被繼續分解。

Jvm建立對象之記憶體配置設定-JVM(七)

由上可以知道,我們是先在棧上配置設定,因為前面說的逃逸分析,标量替換,之後再往堆配置設定。

那棧裡怎麼會放那麼多對象呢?

比如一個main方法裡調用一個方法,這個main方法有一個大的棧空間,裡面的方法會有一個棧幀空間,而這個方法結束的時候,線程會退出,這時候棧幀空間就會釋放,是以後面就繼續可以使用棧幀空間。

四、EDEN

如果對象太大,則會直接進入old代裡。

Jvm建立對象之記憶體配置設定-JVM(七)

我們需要在啟動的時候加參數:-XX:+PrintGCDetails

這時候放入45M的資料(1024byte=1kb,1024kb=1m)

可以看到eden已經滿了,eden區一共有50m的空間,足夠放的下,YoungGen區從圖中可以看到有60M的空間。

後面的from和to都是百分之0,oldGen也是百分之0。

Jvm建立對象之記憶體配置設定-JVM(七)

我們再放入7M的資料讓記憶體配置設定,這時候可以看到eden和from都有放。

放不下則放入oldGen老年代,老年代有45M左右。

前面的45M全部到老年代了,後面新進入的7M則在eden。

Jvm建立對象之記憶體配置設定-JVM(七)

當我們再放3M進去可以看到,還是進入了eden。老年代放的還是剛剛的大對象。

對象是在eden配置設定的,當我們放不下的時候,會生成yongGC也就是MinorGC,新生代回收頻繁,速度比較快。

繼續閱讀