日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

jvm(11)-晚期(运行期)优化

發(fā)布時間:2023/12/3 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 jvm(11)-晚期(运行期)优化 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

【0】README

0.1)本文部分文字描述轉自 “深入理解 jvm”,旨在學習 ?晚期(運行期)優(yōu)化 ?的基礎知識;

【1】概述

1)即時編譯器(JIT=just in time compiler)定義:為了提高熱點代碼的執(zhí)行效率,在運行時,虛擬機將把這些代碼編譯成與 本地平臺相關的機器碼,并進行各種層次的優(yōu)化,完成這個任務的編譯器稱為即時編譯器; 2)熱點代碼:當虛擬機發(fā)現(xiàn)某個方法或代碼塊運行特別頻繁,就會把這些代碼認定為熱點代碼;(干貨——即時編譯器和熱點代碼的定義) Attention)本文提及的編譯器,即時編譯器都是指HotSpot 虛擬機內(nèi)的即時編譯器,虛擬機也是特指HotSpot虛擬機;
【2】 HotSpot 虛擬機內(nèi)的即時編譯器 0)我們需要解決以下問題:
  • problem1)為何HotSpot虛擬機要使用解釋器與編譯器并存的架構?
  • problem2)為何HotSpot虛擬機要實現(xiàn)兩個不同的即時編譯器?
  • problem3)程序何時使用解釋器執(zhí)行?何時使用編譯器執(zhí)行?
  • problem4)哪些程序代碼會被編譯為本地代碼? 如何編譯為本地代碼?
  • problem5)如何從外部觀察即時編譯器的編譯過程和編譯結果?
【2.1】解釋器與編譯器 1)解釋器與編譯器各有優(yōu)勢:
  • 1.1)解釋器的優(yōu)勢:當程序需要迅速啟動和執(zhí)行的時候,解釋器可以首先發(fā)揮作用,省去編譯的時間,立即執(zhí)行;
  • 1.2)編譯器的優(yōu)勢:在程序運行后,隨著時間的推移,編譯器逐漸發(fā)揮作用,把越來越多的代碼編譯成本地代碼之后,可以獲得更高的執(zhí)行效率;

2)HotSpot虛擬機中內(nèi)置了兩個即時編譯器,分別為:Client Compiler 和 Server Compiler, 或簡稱為C1 和 C2 編譯器;用于可以使用 -client 或 -server 參數(shù)去強制指定虛擬機運行在Client 模式或 Server模式; 3)混合模式:解釋器和編譯器搭配使用的方式在虛擬機中叫做 混合模式;(干貨——虛擬機運行模式包括,混合模式+解釋模式+編譯模式)
  • 3.1)解釋模式:使用參數(shù) -Xint 強制虛擬機運行在解釋模式, 這時編譯器完全不介入工作;
  • 3.2)編譯模式:使用參數(shù) -Xcomp?強制虛擬機運行在編譯模式, 這時將優(yōu)先采用編譯方式執(zhí)行程序,但解釋器仍然要求在編譯無法進行的情況下介入執(zhí)行過程;
  • 3.3)通過虛擬機的 -version 命令的輸出結果顯示出這3種模式:

4)分層編譯:為了在程序啟動相應速度與運行效率之間達到最佳平衡,HotSpot 虛擬機還會逐漸啟用分層編譯的策略;分層編譯工具編譯器編譯,優(yōu)化的規(guī)模與耗時,劃分出不同的編譯層次,包括:
  • 4.1)第0層:程序解釋執(zhí)行,解釋器不開啟性能監(jiān)控功能,可觸發(fā)第1層編譯。
  • 4.2)第1層:也成為C1編譯,將字節(jié)碼編譯為本地代碼,進行簡單、可靠的優(yōu)化,如有必要時將加入性能監(jiān)控的邏輯。
  • 4.3)第2層(或2層以上):也成為C2編譯,也是將字節(jié)碼編譯為本地代碼,但是會啟動一些編譯耗時較長的優(yōu)化,甚至會根據(jù)性能監(jiān)控信息進行一些不可靠的激進優(yōu)化。?
  • 4.4)事實上:?用Client Compiler獲取更高的編譯速度,用Server Compiler來獲取更好的編譯質(zhì)量,在解釋執(zhí)行的時候也無須再承擔收集性能監(jiān)控信息的任務。(干貨——Client Compiler 和?Server Compiler的用途)
【2.2】編譯對象與觸發(fā)條件 1)在運行過程中會被即時編譯器編譯的熱點代碼有兩類:即:(干貨——引入熱點代碼)
  • 1.1)被多次調(diào)用的方法;
  • 1.2)被多次執(zhí)行的循環(huán)體;
2)JIT編譯方式和OSR編譯方式(干貨——JIT編譯方式和OSR編譯方式) 2.1)JIT編譯方式:對于第一種情況,由于是由方法調(diào)用觸發(fā)的編譯,因此編譯器會以整個方法作為編譯對象,這種編譯也是虛擬機中標準的JIT編譯方式; 2.2)OSR編譯方式:盡管編譯動作是由循環(huán)體所觸發(fā)的,但編譯器依然會以整個方法作為編譯對象,這種編譯方式因為編譯發(fā)生在方法執(zhí)行過程之中,因此形象地被稱為棧上替換,簡稱為OSR編譯,即方法棧幀還在棧上,方法就被替換了。 3)觸發(fā)條件
  • 3.1)問題一:被多次調(diào)用,在這里的多次具體是多少次?
  • 3.2)問題二:并且虛擬機如何統(tǒng)計一個方法或一段代碼被執(zhí)行過多少次??
  • 3.3)解決了以上問題,就回答了即時編譯器被觸發(fā)的條件;
4)熱點探測 4.1)定義:判斷一段代碼是不是熱點代碼,是不是需要觸發(fā)即時編譯,這樣的行為稱為熱點探測; 4.2)主要的熱點探測判斷方式(method)有兩種,如下:(干貨——熱點探測判斷方式(method))
  • method1)基于采樣的熱點探測:虛擬機會周期性地檢查各種線程的棧頂,如果發(fā)現(xiàn)某個或者某些方法經(jīng)常出現(xiàn)在棧頂,那這個方法就是“熱點方法”。?
優(yōu)點:實現(xiàn)簡單、高效,還可以很容易地獲取方法調(diào)用方法。? 缺點:很難精確地確認一個方法的熱度,因為容易受到線程阻塞或別的外界因素的影響而擾亂熱點探測。
  • method2)基于計數(shù)器的熱點探測:虛擬機會為每個方法建立計數(shù)器,統(tǒng)計方法的執(zhí)行次數(shù),如果執(zhí)行次數(shù)超過一定的闕值就認為它是熱點方法。?
優(yōu)點:統(tǒng)計結構相對來說更加精確與嚴謹。? 缺點:實現(xiàn)起來麻煩,需要為每個方法及建立并維護計數(shù)器,而且不能直接獲取到方法的調(diào)用關系。? 5)在HotSpot中使用的是第二種方法,基于計數(shù)器的熱點探測法,因此它為每個方法準備了兩類計數(shù)器:方法調(diào)用計數(shù)器和回邊計數(shù)器(統(tǒng)計一個方法中循環(huán)體代碼執(zhí)行的次數(shù),在字節(jié)碼中中遇到控制流向后跳轉的指令稱為“回邊”。建立回邊計數(shù)器的目的是為了觸發(fā)OSR編譯。)。(干貨——引入方法調(diào)用計數(shù)器和回邊計數(shù)器) 5.1)方法調(diào)用計數(shù)器(統(tǒng)計方法被調(diào)用次數(shù))
  • 5.1.1)定義:這個計數(shù)器就用于統(tǒng)計方法被調(diào)用的次數(shù),他的默認閾值在 Client模式下是1500次,在 Server模式下是10000次,可以通過 虛擬機參數(shù) -XX: CompileThreshold 來認為設定;
  • Attention)JIT編譯的交互過程:
    • A1)當一個方法被調(diào)用時,會先檢查該方法是否存在被JIT 編譯過的版本:如果存在,則優(yōu)先使用編譯后的本地代碼來執(zhí)行。如果不存在已被編譯過的版本,則將此方法的調(diào)用計數(shù)器值加1,然后判斷方法調(diào)用計數(shù)器與回邊計數(shù)器值之和是否超過方法計數(shù)器的閾值。若超過了,則將會向即時編譯器提交一個該方法的代碼編譯請求;
    • A2)如果不做任何設置執(zhí)行引擎并不會同步等待編譯請求完成,而是繼續(xù)進入解釋器按照解釋方式執(zhí)行字節(jié)碼,直到提交的請求被編譯器編譯完成。當編譯工作完成之后,這個方法的調(diào)用入口地址就會被系統(tǒng)自動改寫成新的,下一次調(diào)用該方法時就會使用已變異的版本,整個JIT 編譯的交互過程如下圖所示:

5.2)回邊計數(shù)器(統(tǒng)計方法循環(huán)體代碼執(zhí)行次數(shù))
  • 5.2.1)作用:是統(tǒng)計一個方法中循環(huán)體代碼執(zhí)行的次數(shù),在字節(jié)碼中遇到控制流向后跳轉的指令稱為”回邊“;顯然,建立回邊計數(shù)器統(tǒng)計的目的是為了觸發(fā)OSR 編譯(==棧上替換編譯);(干貨——回邊計數(shù)器的作用)
  • 5.2.2)設置參數(shù) -XX:OnStackReplacePercentage 來簡介調(diào)整回邊計數(shù)器的閾值,回邊計數(shù)器的閾值的計算公式如下:
    • case1)虛擬機運行在Client模式下:閾值=方法調(diào)用計數(shù)器閾值*OSR比率/100;
    • case2)虛擬機運行在Server模式下:閾值=方法調(diào)用計數(shù)器閾值*(OSR比率-解釋器監(jiān)控比率)/100;
  • 5.2.3)回邊計數(shù)器觸發(fā)即時編譯的過程:當解釋器遇到一條回邊指令時,會先查找將要執(zhí)行的代碼片段是否有已經(jīng)編譯好的version,如果有,他將會優(yōu)先執(zhí)行已編譯的代碼,否則就把回邊計數(shù)器的值加1,然后判斷方法調(diào)用計數(shù)器與回邊計數(shù)器之和是否超過回邊計數(shù)器的閾值。當超過閾值的時候,將會提交一個OSR編譯請求,并且把回邊計數(shù)器的值降低一些,以便繼續(xù)在解釋器中執(zhí)行循環(huán),等待編譯器輸出編譯結果,整個執(zhí)行過程如下圖所示:
Attention)圖11-2 和 圖11-3都僅僅描述了 Client VM 的即時編譯技術,對于Server VM來說,case 或許還更加復雜;
【2.3】編譯過程 1)無論是方法調(diào)用產(chǎn)生的即時編譯請求,還是OSR編譯請求:虛擬機在代碼編譯器還未完成之前,都將按照解釋方式繼續(xù)執(zhí)行,而編譯動作則在后臺的編譯線程中進行; 2)在后臺執(zhí)行編譯的過程中,編譯器做了什么事情呢? 3)對于Client Compiler來說,它是一個簡單快速的三段式編譯器;(干貨——Client 編譯器的編譯過程)
  • step1)在第一個階段:一個平臺獨立的前端將字節(jié)碼構造成一種高級中間代表表示(High Level Intermediate Representation,HIR)。
  • step2)在第二個階段:一個平臺相關的后端從 HIR中產(chǎn)生低級中間代碼表示(Low Level Intermediate Representation, LIR);
  • step3)在第三個階段:最后是在平臺相關的后端使用線性掃描算法在LIR 上分配寄存器,并在LIR上做窺孔優(yōu)化,然后產(chǎn)生機器代碼;
  • Conclusion)整個 Client Compiler 的大致執(zhí)行過程如下圖所示:
4)Server Compiler:該編譯器則是專門面向服務端的典型應用并為服務端的性能配置特別調(diào)整過的編譯器,也是充分優(yōu)化過的高級編譯器,幾乎能達到GNU C++ 編譯器使用 -O2參數(shù)時的優(yōu)化強度; 【2.4】查看及分析即時編譯結果(如何從外部觀察虛擬機的即時編譯行為) 1)看個荔枝 // 測試JIT代碼優(yōu)化過程 public class JITCompileResultTest {public static final int NUM = 15000;public static int doubleValue(int i) {// 這個空循環(huán)用于后面演示 JIT代碼優(yōu)化過程for(int j=0; j<010000; j++);return i * 2;}public static long calculateSum() {long sum = 0;for (int i = 0; i <= 100; i++) {sum += doubleValue(i);}return sum;}public static void main(String[] args) {for (int i = 0; i < NUM; i++) {calculateSum();}} } 對上述代碼的分析(Analysis): 使用參數(shù) -XX: +PrintCompilation 要求虛擬機在即時編譯時將被編譯成本地代碼的方法名稱打印出來;
(此處有文字省略)
【3】編譯優(yōu)化技術 0)java程序員有一個共識:以編譯方式執(zhí)行本地代碼比解釋方式更快,之所以有這樣的共識,除去虛擬機解釋執(zhí)行字節(jié)碼時額外消耗時間的原因外,還有一個重要的原因是 虛擬機設計團隊幾乎把對代碼的所有優(yōu)化措施都集中在了即時編譯器中。所以編譯器產(chǎn)生的本地代碼會比Javac 產(chǎn)生的字節(jié)碼更加優(yōu)秀;(干貨——編譯器產(chǎn)生的本地代碼會比Javac 產(chǎn)生的字節(jié)碼更加優(yōu)秀)
【3.1】優(yōu)化技術概覽 1)看個荔枝 1.0)源代碼
  • step1)優(yōu)化第一步,進行方法內(nèi)聯(lián):主要目的有兩個:一是去除方法調(diào)用的成本,二是為其他優(yōu)化建立良好的基礎,方法內(nèi)聯(lián)膨脹后可以便于在更大范圍上采取后續(xù)的優(yōu)化手段;

  • step2)優(yōu)化第二步,進行冗余訪問消除:(看成是公共子表達式的消除)

  • step3)復寫傳播: 因為在這段程序的邏輯中并沒有必要使用一個額外的變量z,它與變量y 是完全相等的,因此可以使用 y 來代替;

  • step4)無用代碼消除:無用代碼可能是永遠不會被執(zhí)行的代碼,也可能是完全沒有意義的代碼,因此,它又形象地稱為 Dead Code;

Conclusion)我們將繼續(xù)查看如下的幾項最具有代表性的優(yōu)化技術是如何運作的,分別是:(干貨——幾項最具有代表性的編譯優(yōu)化技術)
  • C1)公共子表達式消除;
  • C2)數(shù)組范圍檢查消除;
  • C3)方法內(nèi)聯(lián);
  • C4)逃逸分析;
【3.2】公共子表達式消除 1)定義:如果一個表達式E 已經(jīng)計算過了,并且從先前的計算到現(xiàn)在,E中所有變量的值都沒有發(fā)生變化,那么E 的這次出現(xiàn)就稱為了公共子表達式; 2)看個荔枝: 2.1)如下表達式: int d = (c*b)*12 +a + (a+b*c); 2.2)當這段代碼進入到虛擬機即時編譯器后,它將進行如下優(yōu)化:編譯器檢測到 c*b 與 b*c 是一樣的表達式,且在計算期間b與c的值不會改變,故,這條表達式就可能被視為: ?int d = E * 12 + a + (a+E);
【3.3】 數(shù)組邊界檢查 1)定義:在java語言中,訪問數(shù)組元素的時候,系統(tǒng)將會自動進行上下界的范圍檢查,即檢查i 必須滿足 大于等于0且小于數(shù)組長度;否則拋出一個運行時異常: java.lang.ArrayIndexOutOfBoundsException; 2)如果編譯器只要通過數(shù)據(jù)流分析就可以判定循環(huán)變量的取值范圍永遠在區(qū)間 [0,foo.length]內(nèi),那在整個循環(huán)中就可以吧數(shù)組的上下界檢查消除; 3)problem+solution
  • problem)在安全檢查方面,java要比C 或C++做更多的事情,這些事情成為了一種隱式開銷,如果處理不好它們,就很可能成為一個 java語言比 C/C++ 更慢的因素;
  • solution)要消除這些隱式開銷,其中之一還要避免思路——隱式異常處理,java中空指針檢查和算術運算中除數(shù)為零的檢查都采用了這種思路;(干貨——隱式開銷,隱式異常處理的概念)
4)隱式開銷的荔枝: // 隱式異常處理 public class ImplicitExceptionHandle {static class B {int value;}// 隱式異常優(yōu)化之前的java偽代碼(before)public int before_optimize() {B b = new B();if(b != null) {return b.value;} else {throw new NullPointerException();}}// 隱式異常優(yōu)化之后的java偽代碼(after)public int after_optimize() {try {B b = new B();return b.value;}catch(segment_fault) {uncommon_trap();} } } 【3.4】方法內(nèi)聯(lián) 1)定義:? 把目標方法的代碼“復制”到發(fā)起調(diào)用的方法之中,避免發(fā)生真實的方法調(diào)用。(干貨——方法內(nèi)聯(lián)定義) 2)如果不是即時編譯器做了一些特別的努力,按照經(jīng)典編譯原理的優(yōu)化理論,大多數(shù)的java方法都無法進行內(nèi)聯(lián);
  • 2.1)無法內(nèi)聯(lián)的原因:只有使用 invokespecial 指令調(diào)用的私有方法, 實例構造器,父類方法以及使用invokestaitc指令進行調(diào)用的靜態(tài)方法才是在編譯期進行解析的,除了上述4種方法外,其他的java方法調(diào)用都需要在運行時進行方法接收者的多態(tài)選擇,并且都有可能存在多于一個版本的方法接收者;簡而言之,java語言中默認的實例方法是虛方法;
  • 2.2)對于一個虛方法:?編譯期做內(nèi)聯(lián)的時候根本無法確定應該使用哪個方法版本;
補充-Complementary)虛方法非虛方法虛方法(干貨——虛方法與非虛方法定義)
  • C1)非虛方法:只要能被invokestatic 和 invokespecial 指令調(diào)用的方法,都可以在解析階段中確定唯一的調(diào)用版本,符合這個條件的有靜態(tài)方法,私有方法,實例構造器,父類方法4類,他們在類加載的時候就會把符號引用解析為對該方法的直接引用。這些方法稱為非虛方法;
  • C2)虛方法:其他的方法稱為虛方法(除去final方法);
3)解決虛方法的內(nèi)聯(lián)問題
對上圖的分析(Analysis):
  • A1)CHA==類型繼承關系分析(Class Hierarchy Analysis, CHA):這是一種基于整個應用程序的類型分析技術,它用于確定在目前已經(jīng)加載的類中,某個接口是否有多于一種的實現(xiàn),某個類是否存在子類,子類是否為抽象類等信息;
  • A2)方法內(nèi)聯(lián)(Inline Cache):工作原理是,在未發(fā)生方法調(diào)用之前,內(nèi)聯(lián)緩存狀態(tài)為空,當?shù)谝淮握{(diào)用發(fā)生后,緩存記錄下方法接收者的版本信息,并且每次進行方法調(diào)用時都比較接收者版本,如果以后進來的每次調(diào)用的方法接收者版本都是一樣的,那這個內(nèi)聯(lián)還可以一直用下去。如果發(fā)生了方法接收者不一致的 case, 就說明程序真正使用了虛方法的多態(tài)特性,這時才會取消內(nèi)聯(lián),查找虛方法表進行方法分派;
【3.5】逃逸分析 1)方法逃逸+線程逃逸?(干貨——逃逸分析包括方法逃逸+線程逃逸)
  • 1.1)方法逃逸:分析對象的動態(tài)作用域,當一個對象在方法中被定義后,它可能被外部方法所引用,例如作為調(diào)用參數(shù)傳遞給其他方法,稱為方法逃逸;
  • 1.2)線程逃逸:甚至還有可能被外部線程訪問到,比如賦值給類變量或可以在其他線程中訪問到的實例變量,稱為線程逃逸;
2)如果能證明一個對象不會逃逸到方法或線程之外,即別的方法或線程無法通過任何途徑訪問到這個對象,則可能為這個變量進行一些高效的優(yōu)化,如下所示:(干貨——保證對象不逃逸到方法或線程之外,就可以進行高效優(yōu)化)
  • 2.1)棧上分配:如果確定一個對象不會逃逸出方法之外,那讓這個對象在棧上分配內(nèi)存將是一個不錯的主意,對象所占用的內(nèi)存空間就可以隨棧幀出棧而銷毀;
  • 2.2)同步消除:線程同步本身是一個相對耗時的過程,如果逃逸分析能夠確定一個變量不會逃逸出線程,那這個變量的讀寫肯定不會有競爭,對這個變量實施的同步措施就可以消除掉;
  • 2.3)標量替換
    • 2.3.1)標量定義:它是指一個數(shù)據(jù)已經(jīng)無法再分解成更小的數(shù)據(jù)來表示了,java虛擬機中的原始數(shù)據(jù)類型都不能再進一步分解,他們就可以成為標量;
    • 2.3.2)聚合量定義:如果一個數(shù)據(jù)可以繼續(xù)分解,它被稱為聚合量;
    • 2.3.3)標量替換:如果把一個java對象拆散,根據(jù)程序訪問的情況,將其使用到的成員變量恢復原始類型來訪問就叫做標量替換;那程序真正執(zhí)行的時候,將可能不創(chuàng)建這個對象,而改為直接創(chuàng)建它的若干個被這個方法使用到的成員變量來代替。
  • Attention)
    • A1)逃逸分析技術還不成熟,不推薦使用;
    • A2)不成熟的原因:無法保證逃逸分析的性能收益必定高于它的消耗;
3)如果有需要,并確認對程序運行有益,用戶可以手動開啟逃逸分析
  • 3.1)用戶使用參數(shù) -XX: +DoEscapeAnalysis 來手動開啟逃逸分析;
  • 3.2)開啟之后可以通過參數(shù) -XX: +PrintEscapeAnalysis 來查看分析結果;
  • 3.3)有了逃逸分析支持后,用戶可以使用參數(shù) -XX: +EliminateAllocations 來開啟標量替換:
  • 3.4)使用 +XX:+EliminateLocks 來開啟同步消除;
  • 3.5)使用參數(shù) -XX:+PrintElimianteAllocations 查看標量的替換情況;
  • Attention)盡管目前逃逸分析的技術不是很成熟,但它卻是即時編譯器優(yōu)化技術的一個重要發(fā)展方向,在今后的虛擬機中,逃逸分析技術肯定會支撐起一些列實用有效的優(yōu)化技術
  • (干貨——逃逸分析技術前途無量)
【4】java 與 C/C++ 的編譯器對比(Comparison) 0)java虛擬機的即時編譯器與C/C++ 的靜態(tài)優(yōu)化編譯器相比,會由于以下原因而導致輸出的本地代碼有一些劣勢:
  • C1)因為即時編譯器運行占用的是用戶程序的運行時間:具有很大的時間壓力,它能提供的優(yōu)化手段嚴重受制于編譯成本;?
  • C2)java語言是動態(tài)的類型安全語言:這就意味著需要由虛擬機來確保程序不會違反語言語義后訪問非結構化內(nèi)存。從實現(xiàn)層面上來看,這就意味著虛擬機必須頻繁地進行動態(tài)檢查,如實例方法訪問時檢查空指針,數(shù)組元素訪問時檢查上下界訪問,類型轉換時檢查基礎關系等。總體上仍然要消耗不少的時間;
  • C3)java語言中沒有virtual關鍵字,但使用虛方法的頻率卻遠遠大于 C 或 C++:這意味著運行時對方法接收者進行多態(tài)選擇的頻率要遠遠大于C或C++,也意味著 即時編譯器在進行一些優(yōu)化時的難度要遠遠大于C 或 C++ 的靜態(tài)優(yōu)化編譯器;
  • C4)java語言是可以動態(tài)擴展的語言,運行時加載新的類可能改變程序類型的繼承關系: 這使得很多全局的優(yōu)化都難以進行,因為編譯器無法看見程序的全貌,許多全局的優(yōu)化措施都只能以激進優(yōu)化的方式來完成,編譯器不得不時刻注意并隨著類型的變化而在運行時撤銷或重新進行一些優(yōu)化;
  • C5)java語言中對象的內(nèi)存分配都是在堆上進行的:只有方法中的局部變量才能在棧上分配;而C 或 C++的對象則有多種內(nèi)存分配方式,既可能在堆上分配,也可能在棧上分配,如果可以在棧上分配線程私有的對象,將減輕內(nèi)存回收的壓力;另外,C或C++中主要由用戶程序代碼來回收分配的內(nèi)存,這就不存在無用對象篩選的過程,因此在效率上,也比垃圾收集機制要高;
Conclusion)以上java的劣勢并不是說 java 不如 C或C++了
  • C1)java 語言上的這些性能上的劣勢都是為了換取開發(fā)效率上的優(yōu)勢而付出的代價;動態(tài)安全, 動態(tài)擴展, 垃圾回收這些拖后腿的特性都為 java 的開發(fā)效率做出了貢獻;
  • C2)許多優(yōu)化時 Java的即時編譯器能做而C 或 C++的靜態(tài)優(yōu)化編譯器不能做或做的不好的;
  • C3)java編譯器另外一個紅利是由它的動態(tài)性帶來的: 由于C或C++編譯器所有優(yōu)化都在編譯器完成,以運行期性能監(jiān)控為基礎的優(yōu)化措施它都無法進行;

總結

以上是生活随笔為你收集整理的jvm(11)-晚期(运行期)优化的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。