逃逸分析、棧上分配、標量替換大展神威

程序員小迷 2024-05-02 14:25:23

一、逃逸分析

1.逃逸分析的目的是判斷對象的作用域是否會逃逸出方法體(方法逃逸)或者外部線程(線程逃逸)。

2.注意,任何可以在多個線程之間共享的對象,一定都屬于逃逸對象。

3.若重寫了一個類的finalize方法,則這個類的變量會被標記爲全局逃逸狀態,且會被放在堆內存中。

4.若一個對象不會逃逸到方法或其他線程之外,則可以對此對象進行高效優化。

5.默認情況下32位的hotspot虛擬機都是client模式;64位的的都是server模式。那麽32位的虛擬機就一定是client模式,64位的虛擬機就一定是server模式嗎?當然不是,這個可以通過配置文件來永久性的調整。

配置文件的位置:32位的虛擬機在%JAVA_HOME%/jre/lib/i386/jvm.cfg

64位的虛擬機在%JAVA_HOME%/jre/lib/amd64/jvm.cfg

比如我們用Eclipse或者MyEclipse運行程序,一般使用的都是工具自帶的JRE,虛擬機並不是本地安裝的虛擬機。這時候可以通過在程序中運行下面的語句來查看虛擬機信息:

System.out.println(System.getProperty("java.vm.name"));

6.逃逸分析可以識別出以下幾種情況:

1)全局逃逸:對象可以被外部訪問。

2)局部逃逸:對象只能被方法內的代碼或訪問到此對象的外部方法訪問。

3)無逃逸:對象僅在方法內部使用,外部不可使用。

7.若逃逸分析確定一個變量不會逃逸出線程,則這個變量不會有多線程競爭問題,所以變量的同步措施(例如:鎖)就可以被消除了。

8.逃逸分析是爲其他優化提供依據的分析技術。

-server JVM運行的模式之一, server模式才能進行逃逸分析, JVM運行的模式還有mixed和client。

-XX:+DoEscapeAnalysis:啓用逃逸分析(默認開啓)

-XX:+PrintEscapeAnalysis:查看逃逸分析結果(默認開啓)

-XX:+EliminateAllocations:開啓標量替換(默認開啓)

-XX:+PrintEliminateAllocations:查看標量替換情況(默認開啓)

-XX:+EliminateLocks:開啓鎖消除(默認開啓)

-XX:+PrintGC:打印GC日志

-XX:-UseTLAB:關閉本地線程分配緩沖

TLAB: Thread Local Allocation Buffer(本地線程分配緩沖)

二、棧上分配

1.虛擬機提供的一種優化技術,基本思想是,對于線程私有的對象,將它分配在棧上,而不分配在堆上。好處是對象跟著方法調用自行銷毀,不需要進行垃圾回收,可以提高性能。

2.棧上分配需要的技術基礎爲逃逸分析。

3.若通過逃逸分析確認對象不會被外部訪問到的話,則直接在棧上分配對象。這樣這個對象在棧幀出棧時即被銷毀,可以減少堆內存的使用,降低垃圾回收的壓力。

4.棧的分配與回收比堆快。棧空間較小且高效,適合短生命周期的對象。

5.如何啓用棧上分配:

對棧上分配發生影響的參數有三個,-server、-XX:+DoEscapeAnalysis和-XX:+EliminateAllocations,任何一個發生變化都不會發生棧上分配。因爲啓用逃逸分析和標量替換默認是打開的,所以,JVM的參數只用-server時一樣可以有棧上分配的效果。

三、標量替換

1.若逃逸分析證明一個對象不會被外部訪問,且此對象可以拆分,則可以使用標量替換。這些標量可以直接分配在棧上或寄存器中,可提高程序執行效率。

2.將對象使用到的成員變量以原始類型來訪問就叫做標量替換。

3.標量替換需要的技術基礎爲逃逸分析。

4.標量替換通常在JIT(即時編譯)時進行。

5.標量替換可以大大減少堆內存的占用及垃圾回收壓力。

6.標量替換可以看作是棧上分配的一個特例。

四、總結

基于逃逸分析這個編譯器優化技術,可以使用棧上分配和標量替換等優化手段來提高程序運行性能。

微風不燥,陽光正好,你就像風一樣經過這裏,願你停留的片刻溫暖舒心。

我是程序員小迷(致力于C、C++、Java、Kotlin、Android、Shell、JavaScript、TypeScript、Python等編程技術的技巧經驗分享),若作品對您有幫助,請關注、分享、點贊、收藏、在看、喜歡,您的支持是我們爲您提供幫助的最大動力。

歡迎關注。助您在編程路上越走越好!

0 阅读:2

程序員小迷

簡介:致力于Android、C等編程技術的技巧經驗分享