溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

如何理解JVM本地方法棧&堆

發(fā)布時(shí)間:2021-11-11 16:32:45 來(lái)源:億速云 閱讀:132 作者:柒染 欄目:大數(shù)據(jù)

這期內(nèi)容當(dāng)中小編將會(huì)給大家?guī)?lái)有關(guān)如何理解JVM本地方法棧&堆,文章內(nèi)容豐富且以專業(yè)的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。

今天我們一起了解一下關(guān)于本地方法棧和Java堆的相關(guān)知識(shí)。

 
本地方法棧

本地方法棧與Java虛擬機(jī)棧發(fā)揮的作用相同,區(qū)別在于Java虛擬機(jī)棧是為虛擬機(jī)執(zhí)行Java方法服務(wù),而本地方法棧是為虛擬機(jī)執(zhí)行Native方法服務(wù)。

 
Java堆

Java堆是虛擬機(jī)管理的最大的一塊內(nèi)存區(qū)域,堆主要用來(lái)存放對(duì)象的實(shí)例。Java堆主要分為:

  • 新生代(Eden)
  • 老年代
  • Survivor(s0、s1也可以成為from、to,屬于新生代)

在絕大數(shù)情況下,對(duì)象都會(huì)被分配在新生代,在經(jīng)歷過(guò)一次新生代回收后,如果對(duì)象還存活那么會(huì)進(jìn)入s0或者s1,每經(jīng)過(guò)一次新生代回收,如果對(duì)象存活那么他的年齡將會(huì)加,當(dāng)對(duì)象的年齡到達(dá)一定的條件時(shí)會(huì)進(jìn)入老年代。當(dāng)然如果對(duì)象非常大,超出了新生代的大小,對(duì)象也有可能直接分配在老年代。

隨著JIT編譯器的發(fā)展以及逃逸分析技術(shù)的成熟,棧上分配、標(biāo)量替換等技術(shù)使得對(duì)象分配在堆中變得不再那么絕對(duì)。

 
棧上分配

棧上分配是指對(duì)那些線程私有的對(duì)象可以將他們打散分散在棧上,分配在棧上的好處是隨著函數(shù)調(diào)用結(jié)束對(duì)象自動(dòng)銷(xiāo)毀,不需要垃圾回收器的介入,從而提高系統(tǒng)的性能。

棧上分配的基礎(chǔ)是要進(jìn)行逃逸分析,逃逸分析的目的是判斷對(duì)象的作用域是否可能逃出函數(shù)體。

逃逸分析只有在Server模式下才可以啟動(dòng)(這個(gè)作者由于本人Java環(huán)境是Server環(huán)境,沒(méi)有做驗(yàn)證,如果有讀者感興趣,可以使用Client模式啟動(dòng)做一下驗(yàn)證然后截圖留言)。參數(shù)是:

  • -XX:+DoEscapeAnalysis
public class EscapeAnalysis {
   public static class User {        private int id = 1;        private String name = "xiaoming";    }
   public static void alloc() {        User u = new User();        u.id = 5;        u.name = "xiaohong";    }
   public static void main(String[] args) {        long start = System.currentTimeMillis();        for (int i = 0; i < 100000000; i++) {            alloc();        }        long end = System.currentTimeMillis();        System.out.println(end - start);    }}
 

執(zhí)行以下命令將源碼文件編譯成字節(jié)碼文件并且運(yùn)行字節(jié)碼

javac -d . EscapeAnalysis.javajava -server -Xmx10m -Xms10m -XX:-DoEscapeAnalysis -XX:+PrintGC jvm/heap/EscapeAnalysis
 

由于Java8默認(rèn)開(kāi)啟了逃逸分析,所以我們用-XX:-DoEscapeAnalysis移除逃逸分析看一下效果。

如何理解JVM本地方法棧&堆  


通過(guò)上圖我們發(fā)現(xiàn)由于對(duì)象分配在堆上,但我們指定的最大堆為10m,不夠存儲(chǔ)我們大量User對(duì)象,因此虛擬機(jī)需要不停的進(jìn)行垃圾回收來(lái)釋放堆空間,程序執(zhí)行時(shí)間928ms。

下面我們通過(guò)-XX:-EliminateAllocations將標(biāo)量替換關(guān)閉,也就是說(shuō)不允許對(duì)象打散分配在棧上。

java -server -Xmx10m -Xms10m -XX:+DoEscapeAnalysis -XX:-EliminateAllocations -XX:+PrintGC jvm/heap/EscapeAnalysis
 
如何理解JVM本地方法棧&堆  


當(dāng)我們關(guān)閉標(biāo)量替換以后,會(huì)發(fā)現(xiàn)對(duì)象依舊不能在棧上分配。

下面讓我們看一下當(dāng)我們打開(kāi)逃逸分析和標(biāo)量替換(允許Use對(duì)象的id和name當(dāng)做局部變量在棧上存儲(chǔ)時(shí))執(zhí)行效果:

java -server -Xmx10m -Xms10m -XX:+DoEscapeAnalysis -XX:+EliminateAllocations -XX:+PrintGC jvm/heap/EscapeAnalysis
 
如何理解JVM本地方法棧&堆  


通過(guò)上圖可以看出,我們的程序只進(jìn)行了一次垃圾回收,總運(yùn)行時(shí)間5ms,相比之前接近1s中的運(yùn)行時(shí)間性能翻了將近200倍,可見(jiàn)由于棧上分配的優(yōu)化,使得小對(duì)象可以直接分配在棧上,避免了垃圾回收器的介入,大幅度提高了我們程序的性能。

棧上分配需要同時(shí)開(kāi)啟逃逸分析和標(biāo)量替換,Java8 Server模式下這兩個(gè)參數(shù)都是默認(rèn)開(kāi)啟的。

上述就是小編為大家分享的如何理解JVM本地方法棧&堆了,如果剛好有類似的疑惑,不妨參照上述分析進(jìn)行理解。如果想知道更多相關(guān)知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

jvm
AI