JVM:你知道為什么對象一定在堆中分配嗎
JVM運行時數(shù)據區(qū)域:
JVM運行時的數(shù)據區(qū)域可以分為:虛擬機棧、本地方法棧、方法區(qū)、程序計數(shù)器、堆。一般我們都說一切的對象的分配都是在堆中進行分配的,即使是棧中的對象,棧也只是保存了該對象的引用,真正的對象仍然存儲在堆中。
然而實際上,對象并不總是在堆中進行分配的,這里就需要介紹一下JVM的逃逸分析技術了。JVM會通過逃逸分析技術,對于逃不出方法的對象,會讓其在??臻g上進行分配。
逃逸分析技術:英文稱為 Escape Analysis,是目前JVM中比較前沿的一種優(yōu)化技術,與類型繼承關系分析一樣,并不是直接優(yōu)化代碼的手段,而是為其他優(yōu)化措施提供依據的分析技術。
基本原理:分析對象動態(tài)作用域,當一個對象在方法里面被定義后,它可能被外部方法所引用,例如作為調用參數(shù)傳遞到其他方法中,這種行為被稱為方法逃逸;當一個對象被外部線程訪問到時,比如賦值給可以在其他線程中訪問的實例變量,這種行為稱為線程逃逸。從不逃逸、方法逃逸到線程逃逸,稱為對象由低到高的不同程度的逃逸。
方法逃逸
根據對象的逃逸程度來選擇采用不同的優(yōu)化方案,針對逃逸程度有三種優(yōu)化方案:
- 棧上分配(Stack Allocations):如果能夠確定一個對象不會逃逸出線程之外,可以讓該對象在??臻g上進行分配,對象所占用的內存空間就會隨著棧幀出棧而銷毀。這樣做的好處就是減少資源消耗,對于JVM來說,對垃圾對象進行標記以及回收過程,都會消耗很多的資源,利用棧來分配會減少JVM標記回收對象的數(shù)量,減輕回收壓力。
棧上分配支持方法逃逸,但不能支持線程逃逸,也就是說,對于逃不出方法的對象才能在棧中進行分配
- 標量替換(Scalar Replacement):標量,即一個已經無法在分解成更小的數(shù)據的數(shù)據,比如JVM中原始數(shù)據類型(int,long等);如果一個數(shù)據可以繼續(xù)分解,則稱為聚合量,Java的對象就是典型的聚合量。把一個對象拆散,根據程序的訪問情況,將其用到的成員變量恢復成為原始類型來訪問,稱為標量替換。若對象可以不被方法外部訪問且不會被拆散,則可以不創(chuàng)建對象,直接創(chuàng)建它的成員變量。
不允許對象逃逸出方法范圍
標量替換
- 同步消除:如果一個變量不會逃逸出線程之外,無法被其他線程訪問到,則可以不用進行同步措施。即可以消除掉對該變量的同步操作。不會產生線程安全問題。
逃逸分析技術存在的問題:
- 到目前為止,該技術還未發(fā)展成熟,仍有很大的改進余地
- 逃逸分析的成本非常高,甚至不能保證逃逸分析帶來的性能收益會高于它的消耗
逃逸分析JVM參數(shù)設置:
- -XX:+DoEscapeAnalysis 開啟逃逸分析
- -XX:+PrintEscapeAnalysis 查看逃逸分析
- -XX:+EliminateAllocations 開啟標量替換
- +XX:+EliminateLocks 開啟同步消除
- -XX:+PrintEliminateAllocation 查看標量替換
總結
本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關注腳本之家的更多內容!
相關文章
SpringMVC使用MultipartResolver實現(xiàn)文件上傳
MultipartResolver 用于處理文件上傳,當收到請求時 DispatcherServlet 的 checkMultipart() 方法會調用 MultipartResolver 的 isMultipart() 方法判斷請求中是否包含文件2023-02-02java?集合工具類Collections及Comparable和Comparator排序詳解
這篇文章主要介紹了java集合工具類Collections及Comparable和Comparator排序詳解,文章圍繞主題展開詳細的內容介紹,具有一定的參考價值,需要的小伙伴可以參考一下2022-06-06JavaWeb開發(fā)之JSTL標簽庫的使用、 自定義EL函數(shù)、自定義標簽(帶屬性的、帶標簽體的)
這篇文章主要介紹了JavaWeb開發(fā)之JSTL標簽庫的使用、 自定義EL函數(shù)、自定義標簽(帶屬性的、帶標簽體的),需要的朋友可以參考下2017-02-02