逃逸分析:分離物件、標量替換、同步鎖消除
來源:冰河技術
在JVM的實現中,為了提高JVM的效能和節省記憶體空間,JVM提供了一種叫做“逃逸分析”的特性,而且對於“逃逸分析”這種特性,也是近年來大廠面試常問的知識點。今天,我們就一起來聊聊什麼是逃逸分析。
逃逸分析的概念
先以官方的形式來說下什麼是逃逸分析。逃逸分析就是:一種確定指標動態範圍的靜態分析,它可以分析在程式的哪些地方可以訪問到指標。
在JVM的即時編譯語境下,逃逸分析將判斷新建的物件是否逃逸。即時編譯判斷物件是否逃逸的依據:一種是物件是否被存入堆中(靜態欄位或者堆中物件的例項欄位),另一種就是物件是否被傳入未知程式碼。
直接說這些概念,確實有點暈啊,那我們就來兩個示例。
物件逃逸示例
一種典型的物件逃逸就是:物件被複制給成員變數或者靜態變數,可能被外部使用,此時變數就發生了逃逸。
我們可以用下面的程式碼來表示這個現象。
/**
* @author binghe
* @description 物件逃逸示例1
*/
public class ObjectEscape{
private User user;
public void init(){
user = new User();
}
}
在ObjectEscape類中,存在一個成員變數user,我們在init()方法中,建立了一個User類的物件,並將其賦值給成員變數user。此時,物件被複制給了成員變數,可能被外部使用,此時的變數就發生了逃逸。
另一種典型的場景就是:物件透過return語句返回。如果物件透過return語句返回了,此時的程式並不能確定這個物件後續會不會被使用,外部的執行緒可以訪問到這個變數,此時物件也發生了逃逸。
我們可以用下面的程式碼來表示這個現象。
/**
* @author binghe
* @description 物件逃逸示例2
*/
public class ObjectReturn{
public User createUser(){
User user = new User();
return user;
}
}
給出兩個示例,相信小夥伴們對JVM的逃逸分析多少有點了解了吧,沒錯,JVM透過逃逸分析,能夠分析出新物件的使用範圍,從而決定新物件是否要在堆上進行分配。
還沒完,我們繼續看下逃逸分析的優點,以便於小夥伴們能夠更好的理解逃逸分析。
逃逸分析的優點
逃逸分析的優點總體上來說可以分為三個:物件可能分配在棧上、分離物件或標量替換、消除同步鎖。我們可以使用下圖來表示。
物件可能分配在棧上
JVM透過逃逸分析,分析出新物件的使用範圍,就可能將物件在棧上進行分配。棧分配可以快速地在棧幀上建立和銷燬物件,不用再將物件分配到堆空間,可以有效地減少 JVM 垃圾回收的壓力。
分離物件或標量替換
當JVM透過逃逸分析,確定要將物件分配到棧上時,即時編譯可以將物件打散,將物件替換為一個個很小的區域性變數,我們將這個打散的過程叫做標量替換。將物件替換為一個個區域性變數後,就可以非常方便的在棧上進行分配了。
同步鎖消除
如果JVM透過逃逸分析,發現一個物件只能從一個執行緒被訪問到,則訪問這個物件時,可以不加同步鎖。如果程式中使用了synchronized鎖,則JVM會將synchronized鎖消除。
這裡,需要注意的是:這種情況針對的是synchronized鎖,而對於Lock鎖,則JVM並不能消除。
要開啟同步消除,需要加上 -XX:+EliminateLocks 引數。因為這個引數依賴逃逸分析,所以同時要開啟 -XX:+DoEscapeAnalysis 選項。
所以,並不是所有的物件和陣列,都是在堆上進行分配的,由於即時編譯的存在,如果JVM發現某些物件沒有逃逸出方法,就很有可能被最佳化成在棧上分配。
衍生出的面試題
其實,針對逃逸分析還會衍生出一些典型的面試題,例如:Java中的物件一定是在堆上分配的嗎? 只要我們充分掌握了逃逸分析的原理,回答這種面試題就非常簡單了。
關於面試題
Java中的物件一定是在堆上分配的嗎?
面試官這樣問,如果大家不瞭解逃逸分析的話,那肯定就有些小夥伴心裡會想:我從一開始學習Java時,就知道了:Java中的物件是在堆上建立的,物件的引用是儲存到棧中的,那Java中的物件是在堆上分配的啊!難道不是嗎?
如果你這樣回答,就會被直接Pass掉。
今天,我們介紹完什麼是逃逸分析後,相信各位小夥伴就知道如何去完美的回答這道面試題了吧。
面試題解答思路
總體思路上,你可以這樣回答:Java中的物件不一定是在堆上分配的,因為JVM透過逃逸分析,能夠分析出一個新物件的使用範圍,並以此確定是否要將這個物件分配到堆上。
來自 “ ITPUB部落格 ” ,連結:https://blog.itpub.net/70024924/viewspace-3004151/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Golang逃逸分析Golang
- JAVA物件分析之偏向鎖、輕量級鎖、重量級鎖升級過程Java物件
- cad.net HandOverTo替換物件物件
- JVM的逃逸分析JVM
- 7-15 字串替換 (6分)字串
- 勿對不可變物件做同步/加鎖物件
- Go記憶體逃逸分析Go記憶體
- HTML 替換元素與非替換元素HTML
- Java EE6 事件:JMS的輕量替換Java事件
- 讀寫分離的的資料同步?
- 談談“&”替換標誌的一些特性
- 訊飛 離線語音識別+替換自己的id
- 面試官:Java中物件都存放在堆中嗎?你知道逃逸分析?面試Java物件
- 只想在pojo中替換類物件,怎樣使用jdon?POJO物件
- Go記憶體管理逃逸分析Go記憶體
- 替換tabBartabBar
- 替換(substitution)
- Stata-將變數名稱替換成標籤變數
- linux多執行緒-----同步物件(互斥量、讀寫鎖、條件變數)的屬性Linux執行緒物件變數
- 物件鎖:傳遞物件鎖物件
- 第109天:免殺對抗-PowerShell&混淆&分離載入&特徵修改&EXE生成&填充替換特徵
- 深入理解Java中的逃逸分析Java
- 面試官:簡單聊聊 Go 逃逸分析?面試Go
- js replace替換字串,同時替換多個方法JS字串
- 【02】儘量以const,enum,inline替換#defineinline
- 6、消除過期的物件引用物件
- php替換搜尋標題關鍵字為紅色PHP
- SQL Server 替換SQLServer
- 08:字元替換字元
- RACSubject替換代理
- sed 字串替換字串
- ACM 字串替換ACM字串
- asp字元替換字元
- vi替換命令
- 替換橫槓
- JSON字串轉換為物件直接量JSON字串物件
- Java synchronized物件級別與類級別的同步鎖Javasynchronized物件
- JS中使用正規表示式替換物件裡的大小寫JS物件