老熟女激烈的高潮_日韩一级黄色录像_亚洲1区2区3区视频_精品少妇一区二区三区在线播放_国产欧美日产久久_午夜福利精品导航凹凸

重慶分公司,新征程啟航

為企業(yè)提供網(wǎng)站建設(shè)、域名注冊(cè)、服務(wù)器等服務(wù)

怎么理解Java即時(shí)編譯

這篇文章主要介紹“怎么理解Java即時(shí)編譯”,在日常操作中,相信很多人在怎么理解Java即時(shí)編譯問(wèn)題上存在疑惑,小編查閱了各式資料,整理出簡(jiǎn)單好用的操作方法,希望對(duì)大家解答”怎么理解Java即時(shí)編譯”的疑惑有所幫助!接下來(lái),請(qǐng)跟著小編一起來(lái)學(xué)習(xí)吧!

網(wǎng)站建設(shè)哪家好,找創(chuàng)新互聯(lián)!專注于網(wǎng)頁(yè)設(shè)計(jì)、網(wǎng)站建設(shè)、微信開發(fā)、小程序開發(fā)、集團(tuán)企業(yè)網(wǎng)站建設(shè)等服務(wù)項(xiàng)目。為回饋新老客戶創(chuàng)新互聯(lián)還提供了武城免費(fèi)建站歡迎大家使用!

簡(jiǎn)介

當(dāng) JVM 的初始化完成后,類在調(diào)用執(zhí)行過(guò)程中,執(zhí)行引擎會(huì)把字節(jié)碼轉(zhuǎn)為機(jī)器碼,然后在操作系統(tǒng)中才能執(zhí)行。在字節(jié)碼轉(zhuǎn)換為機(jī)器碼的過(guò)程中,虛擬機(jī)中還存在著一道編譯,那就是即時(shí)編譯。

最初,JVM 中的字節(jié)碼是由解釋器( Interpreter )完成編譯的,當(dāng)虛擬機(jī)發(fā)現(xiàn)某個(gè)方法或代碼塊的運(yùn)行特別頻繁的時(shí)候,就會(huì)把這些代碼認(rèn)定為熱點(diǎn)代碼

為了提高熱點(diǎn)代碼的執(zhí)行效率,在運(yùn)行時(shí),即時(shí)編譯器(JIT,Just In Time)會(huì)把這些代碼編譯成與本地平臺(tái)相關(guān)的機(jī)器碼,并進(jìn)行各層次的優(yōu)化,然后保存到內(nèi)存中。

分類

在 HotSpot 虛擬機(jī)中,內(nèi)置了兩種 JIT,分別為C1 編譯器C2 編譯器,這兩個(gè)編譯器的編譯過(guò)程是不一樣的。

C1 編譯器

C1 編譯器是一個(gè)簡(jiǎn)單快速的編譯器,主要的關(guān)注點(diǎn)在于局部性的優(yōu)化,適用于執(zhí)行時(shí)間較短或?qū)?dòng)性能有要求的程序,也稱為Client Compiler,例如,GUI 應(yīng)用對(duì)界面啟動(dòng)速度就有一定要求。

C2 編譯器

C2 編譯器是為長(zhǎng)期運(yùn)行的服務(wù)器端應(yīng)用程序做性能調(diào)優(yōu)的編譯器,適用于執(zhí)行時(shí)間較長(zhǎng)或?qū)Ψ逯敌阅苡幸蟮某绦?,也稱為Server Compiler,例如,服務(wù)器上長(zhǎng)期運(yùn)行的 Java 應(yīng)用對(duì)穩(wěn)定運(yùn)行就有一定的要求。

分層編譯

在 Java7 之前,需要根據(jù)程序的特性來(lái)選擇對(duì)應(yīng)的 JIT,虛擬機(jī)默認(rèn)采用解釋器和其中一個(gè)編譯器配合工作。

Java7 引入了分層編譯,這種方式綜合了 C1 的啟動(dòng)性能優(yōu)勢(shì)和 C2 的峰值性能優(yōu)勢(shì),我們也可以通過(guò)參數(shù) -client或者-server 強(qiáng)制指定虛擬機(jī)的即時(shí)編譯模式。

分層編譯將 JVM 的執(zhí)行狀態(tài)分為了 5 個(gè)層次:

> 第 0 層:程序解釋執(zhí)行,默認(rèn)開啟性能監(jiān)控功能(Profiling),如果不開啟,可觸發(fā)第二層編譯; > > 第 1 層:可稱為 C1 編譯,將字節(jié)碼編譯為本地代碼,進(jìn)行簡(jiǎn)單、可靠的優(yōu)化,不開啟 Profiling; > > 第 2 層:也稱為 C1 編譯,開啟 Profiling,僅執(zhí)行帶方法調(diào)用次數(shù)和循環(huán)回邊執(zhí)行次數(shù) profiling 的 C1 編譯; > > 第 3 層:也稱為 C1 編譯,執(zhí)行所有帶 Profiling 的 C1 編譯; > > 第 4 層:可稱為 C2 編譯,也是將字節(jié)碼編譯為本地代碼,但是會(huì)啟用一些編譯耗時(shí)較長(zhǎng)的優(yōu)化,甚至?xí)鶕?jù)性能監(jiān)控信息進(jìn)行一些不可靠的激進(jìn)優(yōu)化。

對(duì)于 C1 的三種狀態(tài),按執(zhí)行效率從高至低:第 1 層、第 2層、第 3層。

通常情況下,C2 的執(zhí)行效率比 C1 高出30%以上。

在 Java8 中,默認(rèn)開啟分層編譯,-client-server 的設(shè)置已經(jīng)是無(wú)效的了。如果只想開啟 C2,可以關(guān)閉分層編譯(-XX:-TieredCompilation),如果只想用 C1,可以在打開分層編譯的同時(shí),使用參數(shù):-XX:TieredStopAtLevel=1。

你可以通過(guò) java -version命令行可以直接查看到當(dāng)前系統(tǒng)使用的編譯模式:

C:\Users\Administrator>java -version
java version "1.8.0_45"
Java(TM) SE Runtime Environment (build 1.8.0_45-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.45-b02, mixed mode)

mixed mode代表是默認(rèn)的混合編譯模式,除了這種模式外,我們還可以使用-Xint參數(shù)強(qiáng)制虛擬機(jī)運(yùn)行于只有解釋器的編譯模式下,這時(shí) JIT 完全不介入工作;也可以使用參數(shù)-Xcomp強(qiáng)制虛擬機(jī)運(yùn)行于只有 JIT 的編譯模式下。例如:

C:\Users\Administrator>java -Xint -version
java version "1.8.0_45"
Java(TM) SE Runtime Environment (build 1.8.0_45-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.45-b02, interpreted mode)

C:\Users\Administrator>java -Xcomp -version
java version "1.8.0_45"
Java(TM) SE Runtime Environment (build 1.8.0_45-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.45-b02, compiled mode)

觸發(fā)標(biāo)準(zhǔn)

在 HotSpot 虛擬機(jī)中,熱點(diǎn)探測(cè)是 JIT 的觸發(fā)標(biāo)準(zhǔn)。

> 熱點(diǎn)探測(cè)是基于計(jì)數(shù)器的熱點(diǎn)探測(cè),采用這種方法的虛擬機(jī)會(huì)為每個(gè)方法建立計(jì)數(shù)器統(tǒng)計(jì)方法的執(zhí)行次數(shù),如果執(zhí)行次數(shù)超過(guò)一定的閾值就認(rèn)為它是“熱點(diǎn)方法” 。

虛擬機(jī)為每個(gè)方法準(zhǔn)備了兩類計(jì)數(shù)器:方法調(diào)用計(jì)數(shù)器(Invocation Counter)和回邊計(jì)數(shù)器(Back Edge Counter)。在確定虛擬機(jī)運(yùn)行參數(shù)的前提下,這兩個(gè)計(jì)數(shù)器都有一個(gè)確定的閾值,當(dāng)計(jì)數(shù)器超過(guò)閾值溢出了,就會(huì)觸發(fā) JIT 編譯。

方法調(diào)用計(jì)數(shù)器

方法調(diào)用計(jì)數(shù)器用于統(tǒng)計(jì)方法被調(diào)用的次數(shù),默認(rèn)閾值在 C1 模式下是 1500 次,在 C2 模式在是 10000 次,可通過(guò)-XX: CompileThreshold來(lái)設(shè)定;而在分層編譯的情況下-XX: CompileThreshold指定的閾值將失效,此時(shí)將會(huì)根據(jù)當(dāng)前待編譯的方法數(shù)以及編譯線程數(shù)來(lái)動(dòng)態(tài)調(diào)整。當(dāng)方法計(jì)數(shù)器和回邊計(jì)數(shù)器之和超過(guò)方法計(jì)數(shù)器閾值時(shí),就會(huì)觸發(fā) JIT 編譯器。

回邊計(jì)數(shù)器

回邊計(jì)數(shù)器用于統(tǒng)計(jì)一個(gè)方法中循環(huán)體代碼執(zhí)行的次數(shù),在字節(jié)碼中遇到控制流向后跳轉(zhuǎn)的指令稱為“回邊”(Back Edge),該值用于計(jì)算是否觸發(fā) C1 編譯的閾值,在不開啟分層編譯的情況下,C1 默認(rèn)為 13995,C2 默認(rèn)為 10700,可通過(guò) -XX: OnStackReplacePercentage=N來(lái)設(shè)置;而在分層編譯的情況下,-XX: OnStackReplacePercentage指定的閾值同樣會(huì)失效,此時(shí)將根據(jù)當(dāng)前待編譯的方法數(shù)以及編譯線程數(shù)來(lái)動(dòng)態(tài)調(diào)整。

建立回邊計(jì)數(shù)器的主要目的是為了觸發(fā) OSR(On StackReplacement)編譯,即棧上編譯。在一些循環(huán)周期比較長(zhǎng)的代碼段中,當(dāng)循環(huán)達(dá)到回邊計(jì)數(shù)器閾值時(shí),JVM 會(huì)認(rèn)為這段是熱點(diǎn)代碼,JIT 編譯器就會(huì)將這段代碼編譯成機(jī)器語(yǔ)言并緩存,在該循環(huán)時(shí)間段內(nèi),會(huì)直接將執(zhí)行代碼替換,執(zhí)行緩存的機(jī)器語(yǔ)言。

優(yōu)化技術(shù)

JIT 編譯運(yùn)用了一些經(jīng)典的編譯優(yōu)化技術(shù)來(lái)實(shí)現(xiàn)代碼的優(yōu)化,即通過(guò)一些例行檢查優(yōu)化,可以智能地編譯出運(yùn)行時(shí)的最優(yōu)性能代碼。主要有兩種:方法內(nèi)聯(lián)逃逸分析

方法內(nèi)聯(lián)

調(diào)用一個(gè)方法通常要經(jīng)歷壓棧和出棧。調(diào)用方法是將程序執(zhí)行順序轉(zhuǎn)移到存儲(chǔ)該方法的內(nèi)存地址,將方法的內(nèi)容執(zhí)行完后,再返回到執(zhí)行該方法前的位置。

這種執(zhí)行操作要求在執(zhí)行前保護(hù)現(xiàn)場(chǎng)并記憶執(zhí)行的地址,執(zhí)行后要恢復(fù)現(xiàn)場(chǎng),并按原來(lái)保存的地址繼續(xù)執(zhí)行。 因此,方法調(diào)用會(huì)產(chǎn)生一定的時(shí)間和空間方面的開銷(其實(shí)可以理解為一種上下文切換的精簡(jiǎn)版)。

那么對(duì)于那些方法體代碼不是很大,又頻繁調(diào)用的方法來(lái)說(shuō),這個(gè)時(shí)間和空間的消耗會(huì)很大。

方法內(nèi)聯(lián)的優(yōu)化行為就是把目標(biāo)方法的代碼復(fù)制到發(fā)起調(diào)用的方法之中,避免發(fā)生真實(shí)的方法調(diào)用。

JVM 會(huì)自動(dòng)識(shí)別熱點(diǎn)方法,并對(duì)它們使用方法內(nèi)聯(lián)進(jìn)行優(yōu)化。我們可以通過(guò)-XX:CompileThreshold來(lái)設(shè)置熱點(diǎn)方法的閾值。但要強(qiáng)調(diào)一點(diǎn),熱點(diǎn)方法不一定會(huì)被 JVM 做內(nèi)聯(lián)優(yōu)化,如果這個(gè)方法體太大了,JVM 將不執(zhí)行內(nèi)聯(lián)操作。而方法體的大小閾值,我們也可以通過(guò)參數(shù)設(shè)置來(lái)優(yōu)化:

  1. 經(jīng)常執(zhí)行的方法,默認(rèn)情況下,方法體大小小于 325 字節(jié)的都會(huì)進(jìn)行內(nèi)聯(lián),我們可以通過(guò)-XX:MaxFreqInlineSize=N來(lái)設(shè)置大小值;

  2. 不是經(jīng)常執(zhí)行的方法,默認(rèn)情況下,方法大小小于 35 字節(jié)才會(huì)進(jìn)行內(nèi)聯(lián),我們也可以通過(guò)-XX:MaxInlineSize=N來(lái)重置大小值。

之后我們就可以通過(guò)配置 JVM 參數(shù)來(lái)查看到方法被內(nèi)聯(lián)的情況:

// 在控制臺(tái)打印編譯過(guò)程信息
-XX:+PrintCompilation
// 解鎖對(duì) JVM 進(jìn)行診斷的選項(xiàng)參數(shù)。默認(rèn)是關(guān)閉的,開啟后支持一些特定參數(shù)對(duì) JVM 進(jìn)行診斷
-XX:+UnlockDiagnosticVMOptions
// 將內(nèi)聯(lián)方法打印出來(lái)
-XX:+PrintInlining

熱點(diǎn)方法的優(yōu)化可以有效提高系統(tǒng)性能,一般我們可以通過(guò)以下幾種方式來(lái)提高方法內(nèi)聯(lián):

  1. 通過(guò)設(shè)置 JVM 參數(shù)來(lái)減小熱點(diǎn)閾值或增加方法體閾值,以便更多的方法可以進(jìn)行內(nèi)聯(lián),但這種方法意味著需要占用更多地內(nèi)存;

  2. 在編程中,避免在一個(gè)方法中寫大量代碼,習(xí)慣使用小方法體;

  3. 盡量使用 final、private、static 關(guān)鍵字修飾方法,編碼方法因?yàn)槔^承,會(huì)需要額外的類型檢查。

> 此處就聯(lián)系到了最開始提出的觀點(diǎn),一個(gè)方法中的內(nèi)容越少,當(dāng)該方法經(jīng)常被執(zhí)行時(shí),則容易進(jìn)行方法內(nèi)聯(lián),從而優(yōu)化性能。

逃逸分析

逃逸分析(Escape Analysis)是判斷一個(gè)對(duì)象是否被外部方法引用或外部線程訪問(wèn)的分析技術(shù),編譯器會(huì)根據(jù)逃逸分析的結(jié)果對(duì)代碼進(jìn)行優(yōu)化。

可以通過(guò)JVM參數(shù)進(jìn)行設(shè)置:

-XX:+DoEscapeAnalysis 開啟逃逸分析(jdk1.8 默認(rèn)開啟)
-XX:-DoEscapeAnalysis 關(guān)閉逃逸分析

其具體優(yōu)化方法主要有三種:棧上分配鎖消除、標(biāo)量替換。

棧上分配

在 Java 中默認(rèn)創(chuàng)建一個(gè)對(duì)象是在堆中分配內(nèi)存的,而當(dāng)堆內(nèi)存中的對(duì)象不再使用時(shí),則需要通過(guò)垃圾回收機(jī)制回收,這個(gè)過(guò)程相對(duì)分配在棧中的對(duì)象的創(chuàng)建和銷毀來(lái)說(shuō),更消耗時(shí)間和性能。

這個(gè)時(shí)候,逃逸分析如果發(fā)現(xiàn)一個(gè)對(duì)象只在方法中使用,就會(huì)將對(duì)象分配在棧上。

但是,HotSpot 虛擬機(jī)目前的實(shí)現(xiàn)導(dǎo)致棧上分配實(shí)現(xiàn)比較復(fù)雜,可以說(shuō),在 HotSpot 中暫時(shí)沒(méi)有實(shí)現(xiàn)這項(xiàng)優(yōu)化,所以大家可能暫時(shí)無(wú)法體會(huì)到這種優(yōu)化(我看的資料顯示在 Java8 中還沒(méi)有實(shí)現(xiàn),如果大家有什么其他的發(fā)現(xiàn),歡迎留言)。

鎖消除

如果是在單線程環(huán)境下,其實(shí)完全沒(méi)有必要使用線程安全的容器,但就算使用了,因?yàn)椴粫?huì)有線程競(jìng)爭(zhēng),這個(gè)時(shí)候 JIT 編譯會(huì)對(duì)這個(gè)對(duì)象的方法鎖進(jìn)行鎖消除。例如:

	public static String getString(String s1, String s2) {
		StringBuffer sb = new StringBuffer();
		sb.append(s1);
		sb.append(s2);
		return sb.toString();
		}

可以通過(guò)JVM參數(shù)進(jìn)行設(shè)置:

-XX:+EliminateLocks 開啟鎖消除(jdk1.8 默認(rèn)開啟)
-XX:-EliminateLocks 關(guān)閉鎖消除

標(biāo)量替換

逃逸分析證明一個(gè)對(duì)象不會(huì)被外部訪問(wèn),如果這個(gè)對(duì)象可以被拆分的話,當(dāng)程序真正執(zhí)行的時(shí)候可能不創(chuàng)建這個(gè)對(duì)象,而直接創(chuàng)建它的成員變量來(lái)代替。將對(duì)象拆分后,可以分配對(duì)象的成員變量在棧或寄存器上,原本的對(duì)象就無(wú)需分配內(nèi)存空間了。這種編譯優(yōu)化就叫做標(biāo)量替換。

例如:

	public void foo() {
		TestInfo info = new TestInfo();
		info.id = 1;
		info.count = 99;
		// to do something
	}

逃逸分析后,代碼會(huì)被優(yōu)化為:

	public void foo() {
		id = 1;
		count = 99;
		// to do something
	}

可以通過(guò)JVM參數(shù)進(jìn)行設(shè)置:

-XX:+EliminateAllocations 開啟標(biāo)量替換(jdk1.8 默認(rèn)開啟)
-XX:-EliminateAllocations 關(guān)閉就可以了

到此,關(guān)于“怎么理解Java即時(shí)編譯”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識(shí),請(qǐng)繼續(xù)關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)?lái)更多實(shí)用的文章!


新聞名稱:怎么理解Java即時(shí)編譯
路徑分享:http://www.xueling.net.cn/article/igpsjj.html

其他資訊

在線咨詢
服務(wù)熱線
服務(wù)熱線:028-86922220
TOP
主站蜘蛛池模板: 亚洲一区二区三区在线观看精品中文 | 免费观看黄色12片一级视频 | 无码超乳爆乳中文字幕久久 | 人人干人人草 | 久久综合高清 | 亚洲综合激情五月丁香六月 | 爱啪啪av导航 | 中文字幕免费在线观看视频 | 久久久久亚洲av无码专区蜜芽 | 久久免费看 | 91蜜桃婷婷狠狠久久综合9色 | 亚洲熟妇AV一区二区三区 | 中文字幕第35页 | 成人h动漫精品一区二 | 国产大胸A在线观看 | 国产人成在线视频 | 亚洲性色av一区二区三区 | 在线小视频 | 国产精品美女视频网站 | 在线1区 | 亚洲欧美日韩综合久久久久 | 2022国产成人精品视频人 | 欧洲裸毛BBBBBXXXX | 91色精品视频在线 | 韩国日本一区二区三区 | av毛片在线观看地址 | 久草成人在线观看 | 好爽进去了视频在线观看国版 | 国产亚洲免费在线观看 | 挺进丰满老师屁股白浆视频 | 欧美不卡一区二区三区 | 久久亚洲精品成人 | 久久久久久久久久久久福利 | 夜鲁夜鲁狠鲁天天在线 | 国产yw851.c免费观看网站 | 免费看我的前半生 | 亚洲第一福利视频 | 亚洲色成人中文字幕网站 | 最新国产精品亚洲 | 中国一级簧色带免费看 | 久久ww|