您好,登錄后才能下訂單哦!
這期內容當中小編將會給大家帶來有關如何理解JVM本地方法棧&堆,文章內容豐富且以專業的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。
今天我們一起了解一下關于本地方法棧和Java堆的相關知識。
本地方法棧與Java虛擬機棧發揮的作用相同,區別在于Java虛擬機棧是為虛擬機執行Java方法服務,而本地方法棧是為虛擬機執行Native方法服務。
Java堆是虛擬機管理的最大的一塊內存區域,堆主要用來存放對象的實例。Java堆主要分為:
在絕大數情況下,對象都會被分配在新生代,在經歷過一次新生代回收后,如果對象還存活那么會進入s0或者s1,每經過一次新生代回收,如果對象存活那么他的年齡將會加,當對象的年齡到達一定的條件時會進入老年代。當然如果對象非常大,超出了新生代的大小,對象也有可能直接分配在老年代。
隨著JIT編譯器的發展以及逃逸分析技術的成熟,棧上分配、標量替換等技術使得對象分配在堆中變得不再那么絕對。
棧上分配是指對那些線程私有的對象可以將他們打散分散在棧上,分配在棧上的好處是隨著函數調用結束對象自動銷毀,不需要垃圾回收器的介入,從而提高系統的性能。
棧上分配的基礎是要進行逃逸分析,逃逸分析的目的是判斷對象的作用域是否可能逃出函數體。
逃逸分析只有在Server模式下才可以啟動(這個作者由于本人Java環境是Server環境,沒有做驗證,如果有讀者感興趣,可以使用Client模式啟動做一下驗證然后截圖留言)。參數是:
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);
}
}
執行以下命令將源碼文件編譯成字節碼文件并且運行字節碼
javac -d . EscapeAnalysis.javajava -server -Xmx10m -Xms10m -XX:-DoEscapeAnalysis -XX:+PrintGC jvm/heap/EscapeAnalysis
由于Java8默認開啟了逃逸分析,所以我們用-XX:-DoEscapeAnalysis移除逃逸分析看一下效果。
通過上圖我們發現由于對象分配在堆上,但我們指定的最大堆為10m,不夠存儲我們大量User對象,因此虛擬機需要不停的進行垃圾回收來釋放堆空間,程序執行時間928ms。
下面我們通過-XX:-EliminateAllocations將標量替換關閉,也就是說不允許對象打散分配在棧上。
java -server -Xmx10m -Xms10m -XX:+DoEscapeAnalysis -XX:-EliminateAllocations -XX:+PrintGC jvm/heap/EscapeAnalysis
當我們關閉標量替換以后,會發現對象依舊不能在棧上分配。
下面讓我們看一下當我們打開逃逸分析和標量替換(允許Use對象的id和name當做局部變量在棧上存儲時)執行效果:
java -server -Xmx10m -Xms10m -XX:+DoEscapeAnalysis -XX:+EliminateAllocations -XX:+PrintGC jvm/heap/EscapeAnalysis
通過上圖可以看出,我們的程序只進行了一次垃圾回收,總運行時間5ms,相比之前接近1s中的運行時間性能翻了將近200倍,可見由于棧上分配的優化,使得小對象可以直接分配在棧上,避免了垃圾回收器的介入,大幅度提高了我們程序的性能。
棧上分配需要同時開啟逃逸分析和標量替換,Java8 Server模式下這兩個參數都是默認開啟的。
上述就是小編為大家分享的如何理解JVM本地方法棧&堆了,如果剛好有類似的疑惑,不妨參照上述分析進行理解。如果想知道更多相關知識,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。