一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - Java JVM編譯策略案例詳解

Java JVM編譯策略案例詳解

2021-11-25 14:13codecraft Java教程

這篇文章主要介紹了Java JVM編譯策略案例詳解,本篇文章通過簡要的案例,講解了該項技術的了解與使用,以下就是詳細內容,需要的朋友可以參考下

解釋器

當虛擬機啟動時,解釋器可以首先發揮作用,而不必等待編譯器全部編譯完成再執行,這樣可以省去許多不必要的編譯時間。并且隨著程序運行時間的推移,編譯器逐漸發揮作用,根據熱點探測功能,,將有價值的字節碼編譯為本地機器指令,以換取更高的程序執行效率。

hotspot中內嵌有2個JIT編譯器,分別為Client Compiler,Server Compiler,但大多數情況下我們稱之為C1編譯器和C2編譯器。

C1編譯器

client compiler,又稱C1編譯器,較為輕量,只做少量性能開銷比較高的優化,它占用內存較少,適合于桌面交互式應用。在寄存器分配策略上,JDK6以后采用的為線性掃描寄存器分配算法,其他方面的優化,主要有方法內聯、去虛擬化、冗余消除等。

A、方法內聯

多個方法調用,執行時要經歷多次參數傳遞,返回值傳遞及跳轉等,C1采用方法內聯,把調用到的方法的指令直接植入當前方法中。-XX:+PringInlining來查看方法內聯信息,-XX:MaxInlineSize=35控制編譯后文件大小。

B、去虛擬化

是指在裝載class文件后,進行類層次的分析,如果發現類中的方法只提供一個實現類,那么對于調用了此方法的代碼,也可以進行方法內聯,從而提升執行的性能。

C、冗余消除

在編譯時根據運行時狀況進行代碼折疊或消除。

C2編譯器

Server compiler,稱為C2編譯器,較為重量,采用了大量傳統編譯優化的技巧來進行優化,占用內存相對多一些,適合服務器端的應用。和C1的不同主要在于寄存器分配策略及優化范圍,寄存器分配策略上C2采用的為傳統的圖著色寄存器分配算法,由于C2會收集程序運行信息,因此其優化范圍更多在于全局優化,不僅僅是一個方塊的優化。收集的信息主要有:分支的跳轉/不跳轉的頻率、某條指令上出現過的類型、是否出現過空值、是否出現過異常等。

逃逸分析是C2進行很多優化的基礎,它根據運行狀態來判斷方法中的變量是否會被外部讀取,如不會則認為此變量是不會逃逸的,那么在編譯時會做標量替換、棧上分配和同步消除等優化。

(1)標量替換

簡單地說,就是用標量替換聚合量。這樣做的好處是如果創建的對象并未用到其中的全部變量,則可以節省一定的內存。對于代碼執行而言,無需去找對象的引用,也會更快一些。

(2)棧上分配

如果point沒有逃逸,那么C2會選擇在棧上直接創建Point對象的實例,而不是在JVM堆上。在棧上分配的好處一方面是加快速度,另一方面是回收時隨著方法的結束,對象被回收了。

(3)同步消除

如果發現同步的對象未逃逸,那也就沒有必要進行同步了,C2編譯時會直接去掉同步。

C2還會基于擁有的運行信息來做其他優化,比如編譯分支頻率執行高的代碼等。

運行后C1、C2編譯出來的機器碼如果不再符合優化條件,則會進行逆優化,也就是回到解釋執行的方式,例如基于類層次分析編譯的代碼,當有新的相應的接口來實現類加入時,就執行逆優化。

OSR編譯

除了C1、C2外,還有OSR(On Stack Replace)編譯,只替換循環代碼體的入口,C1、C2替換的是方法調用的入口。因此OSR編譯后會出現的現象是方法的整段代碼被編譯了,但是只有循環體部分才執行編譯后的機器碼,其他部分仍是解釋執行。

當機器配置CPU超過2核且內存超過2G,默認為server模式,32位的windows始終選擇的是client模式。

分層編譯

Java7默認開啟分層編譯(tiered compilation)策略,由C1編譯器和C2編譯器相互協作共同來執行編譯任務。C1編譯器會對字節碼進行簡單和可靠的優化,以達到更快的編譯速度;C2編譯器會啟動一些編譯耗時更長的優化,以獲取更好的編譯質量。

  1. 解釋器不再收集運行狀態信息,只用于啟動并觸發C1編譯
  2. C1編譯后生成帶收集運行信息的代碼
  3. C2編譯,基于C1編譯后代碼收集的運行信息進行激進優化,當激進優化的假設不成立時,再退回使用C1編譯的代碼

程序在未編譯期間解釋執行有個閾值,SunJDK主要依據方法上的兩個計數器是否超過閾值來判斷:

  • A、調用計數器,即方法被調用的次數,CompileThreshold,該值是指當方法被調用多少次后,就編譯為機器碼,client模式默認為1500次,server模式默認為1萬次,可以在啟動時添加-XX:CompileThreshold=10000來設置該值。

  • B、回邊計數器,即方法中循環執行部分代碼的執行次數,OnStackReplacePercentage,該值用于/參與計算是否觸發OSR編譯的閾值,client默認為933,sever默認為140,可以通過-XX: OnStackReplacePercentage=140來設置。

client模式下的計算規則為CompileThreshold*OnStackReplacePercentage/100,
server模式下計算規則為CompileThreshold*(OnStackReplacePercentage-InterpreterProfilePercentage)/100。InterpreterProfilePercentage,默認為33。

當方法上的回邊計數器到達這個值時,觸發后臺的OSR編譯,并將方法上累積的調用計數器設置為CompileThreshold 的值,同時將回邊計數器設置為CompileThreshold/2的值。這樣做一方面是為了避免OSR編譯頻繁被觸發,另一方面是以便當方法被再次調用時即觸發正常的編譯,當累積的回邊計數器的值再次達到該值時先檢查OSR編譯是否完成,如果已完成,則在執行循環體的代碼時進入編譯后的代碼,如果未完成,繼續把當前回邊計數器的累計值再減掉一些,默認情況下,對于回邊的情況,server模式下只要回邊次數達到10700次(10000*(140-33)),就會觸發OSR編譯。

解釋器與編譯器并存

如果選用完全解釋策略,那么編譯器將停止所有的工作,字節碼將完全依靠解釋器逐行解釋執行。
如果選用完全編譯策略,那么解釋器仍然會在編譯器無法進行的特殊情況下介入運行,這主要是確保程序能夠最終順序執行。

SunJDK之所以未選擇在啟動時即編譯成機器碼的原因如下:

  1. 靜態編譯并不能根據程序的運行狀態來優化執行的代碼,C2這種方式是根據運行狀態來進行動態編譯的,例如分支判斷、逃逸分析等,這些措施會對提升程序執行的性能起到很大的幫助,在靜態編譯的情況下是無法實現的,給C2收集運行數據越長的時間,編譯出來的代碼會越優。
  2. 解釋執行比編譯執行更節省內存
  3. 啟動時解釋執行的啟動速度比編譯再啟動更快。

到此這篇關于Java JVM編譯策略案例詳解的文章就介紹到這了,更多相關Java JVM編譯策略內容請搜索服務器之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持服務器之家!

原文鏈接:https://segmentfault.com/a/1190000004649033

延伸 · 閱讀

精彩推薦
  • Java教程升級IDEA后Lombok不能使用的解決方法

    升級IDEA后Lombok不能使用的解決方法

    最近看到提示IDEA提示升級,尋思已經有好久沒有升過級了。升級完畢重啟之后,突然發現好多錯誤,本文就來介紹一下如何解決,感興趣的可以了解一下...

    程序猿DD9332021-10-08
  • Java教程Java8中Stream使用的一個注意事項

    Java8中Stream使用的一個注意事項

    最近在工作中發現了對于集合操作轉換的神器,java8新特性 stream,但在使用中遇到了一個非常重要的注意點,所以這篇文章主要給大家介紹了關于Java8中S...

    阿杜7482021-02-04
  • Java教程Java實現搶紅包功能

    Java實現搶紅包功能

    這篇文章主要為大家詳細介紹了Java實現搶紅包功能,采用多線程模擬多人同時搶紅包,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙...

    littleschemer13532021-05-16
  • Java教程Java使用SAX解析xml的示例

    Java使用SAX解析xml的示例

    這篇文章主要介紹了Java使用SAX解析xml的示例,幫助大家更好的理解和學習使用Java,感興趣的朋友可以了解下...

    大行者10067412021-08-30
  • Java教程20個非常實用的Java程序代碼片段

    20個非常實用的Java程序代碼片段

    這篇文章主要為大家分享了20個非常實用的Java程序片段,對java開發項目有所幫助,感興趣的小伙伴們可以參考一下 ...

    lijiao5352020-04-06
  • Java教程xml與Java對象的轉換詳解

    xml與Java對象的轉換詳解

    這篇文章主要介紹了xml與Java對象的轉換詳解的相關資料,需要的朋友可以參考下...

    Java教程網2942020-09-17
  • Java教程Java BufferWriter寫文件寫不進去或缺失數據的解決

    Java BufferWriter寫文件寫不進去或缺失數據的解決

    這篇文章主要介紹了Java BufferWriter寫文件寫不進去或缺失數據的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望...

    spcoder14552021-10-18
  • Java教程小米推送Java代碼

    小米推送Java代碼

    今天小編就為大家分享一篇關于小米推送Java代碼,小編覺得內容挺不錯的,現在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧...

    富貴穩中求8032021-07-12
主站蜘蛛池模板: 日本在线视频免费观看 | 欧美一区二区三区视视频 | 欧美福利在线观看 | 色小孩导航 | 精品久久综合一区二区 | 无码区国产区在线播放 | 成年男女免费大片在线观看 | 国产人成激情视频在线观看 | 火影忍者羞羞 | cao逼视频 | 欧美一区精品二区三区 | 人成网站在线观看 | xxxxx性中国hd | 国内自拍2020| 公交车上插入 | 日韩无遮挡大尺度啪啪影片 | 无限国产资源 | 欧美国产日韩1区俺去了 | 我的美女奴隶 | chinese男gay| 国产精品福利在线观看入口 | 国内精品久久久久久中文字幕 | 明星ai智能人脸替换造梦在线播放 | 成人网址大全 | 好大好深受不了了快进来 | 嫩草影院永久一二三入口 | 欧美高清免费一级在线 | 第一次不是你高清在线观看 | 小伙无套内射老女人 | 奇米影视999| 高中生放荡日记高h娜娜 | 精品欧美日韩一区二区三区 | 色男人综合 | 性欧美hd| 91桃花| 欧美区视频 | 国产v在线在线观看羞羞答答 | 插鸡网站 | 久久永久视频 | 毛片免费的 | 韩国久久 |