【JVM詳解四】執行引擎

一、概述

Java程序運行時,JVM會加載.class字節碼文件,但是字節碼并不能直接運行在操作系統之上,而JVM中的執行引擎就是負責將字節碼轉化為對應平臺的機器碼讓CPU運行的組件。

執行引擎是JVM核心的組成部分之一。可以把JVM架構分成三部分,如下圖所示:

?執行引擎位于JVM的最下層(圖中虛線框部分),可以粗略地看到執行引擎負責和運行時數據區交互。

二、計算機語言的發展史

在講解執行引擎之前,需要知道什么是機器碼、匯編語言、高級語言以及為什么會有Java字節碼的出現。

2.1 機器碼

各種用 0 和 1 組成的二進制編碼方式表示的指令,叫作機器指令碼,簡稱機器碼。

計算機發展的初始階段,人們就用機器碼編寫程序,我們也稱為機器語言。機器語言雖然能夠被計算機理解和接受,但由于可讀性差不便于人類讀寫,并且用它編程容易出差錯。使用機器碼編寫的程序一經輸入計算機,CPU可以直接讀取運行,因此和其他語言編的程序相比,執行速度最快。機器碼與CPU緊密相關,所以不同種類的CPU所對應的機器碼也就不同。

2.2 匯編語言

由于機器碼是由0和1組成的二進制序列,可讀性實在太差,于是人們發明了指令。

指令就是把機器碼中特定的0和1序列,簡化成對應的指令(一般為英文簡寫,如mov、inc等),可讀性稍好,這就是我們常說的匯編語言。在匯編語言中,用助記符 (Mnemonics) 代替機器碼的操作碼,用地址符號 (Symbol) 或標號 (Label) 代替指令或操作數的地址。

不同的硬件平臺,各自支持的指令是有差別的。因此每個平臺所支持的指令,稱為對應平臺的指令集,如常見的x86指令集對應的是x86架構的平臺,ARM指令集對應的是ARM架構的平臺。不同平臺之間指令不可以直接移植。

由于計算機只認識機器碼,所以用匯編語言編寫的程序還必須經過匯編器轉換為機器語言,計算機才能識別和執行。

2.3 高級語言

為了使計算機用戶編程序更容易些,后來就出現了各種高級計算機語言。比如C、C++等更容易讓人識別的語言。

高級語言則相對匯編語言更易于編寫,有更好的可讀性,一般編譯器會將高級語言轉換成匯編語言,然后再由匯編器轉換為機器指令由計算機執行。

2.4 字節碼

字節碼是一種中間狀態(中間碼)的二進制代碼(文件),需要轉譯后才能成為機器碼。Java 程序可以通過編譯器將源碼編譯成 Java 字節碼,特定平臺上的虛擬機將字節碼轉譯為可以直接執行的指令,也就實現了跨平臺性。如下圖所示:

三、執行引擎工作過程

  1. 執行引擎在執行過程中,需要執行什么樣的字節碼指令取決于PC寄存器(程序計數器);
  2. 每執行完一項指令操作之后,PC寄存器會更新下一條需要執行的指令地址;
  3. 方法執行過程中,執行引擎可能會通過局部變量表中的對象引用準確定位到 Java 堆中的對象實例信息,以及通過對象頭中的元數據信息定位到目標對象的類型信息。
Java執行引擎包括以下組成部分:
  • 解釋器
  • JIT編譯器
  • 垃圾收集器

3.1 解釋器

解釋器就是一個運行時的“翻譯者”,將字節碼指令翻譯為對應平臺的本地機器指令由CPU執行,當一條指令執行完成后再根據PC寄存器中記錄的下一條指令執行解釋操作。

JVM設計者的初衷是為了滿足Java程序實現跨平臺特性,因此避免采用靜態編譯的方式直接生成機器碼,從而誕生了實現解釋器在運行時采用逐行解釋字節碼執行程序的想法。

3.2 JIT(Just-In-Time)編譯器

當執行某些頻繁被調用的代碼(比如for循環中的代碼)時,如果按照解釋執行,效率非常低,這種被頻繁調用的代碼成為熱點代碼。為了提高熱點代碼的執行效率,在運行時,JIT編譯器則會將這些代碼編譯成與本地平臺有關的機器碼,并進行各種層次的優化。

JIT的構成組件包括:

  • 中間代碼生成器——生成中間代碼
  • 代碼優化器——優化中間代碼
  • 目標代碼生成器——生成機器碼或本地代碼
  • 分析器——負責查找熱點代碼

3.2.1 JIT編譯器類型

在 Hotspot 虛擬機中內置了兩種JIT編譯器:

  • C1編譯器:主要關注點在于局部性能優化,適用于執行時間短或對啟動性能有要求的程序,如:GUI應用,C1編譯器也被稱為Client Compiler。
  • C2編譯器:為長期運行的服務端應用程序做性能優化的編譯器,適用于執行時間較長或對峰值性能有要求的程序,C2編譯器也被稱為Server Compiler。
Graal編譯器:用Java實現的JIT編譯器,JDK10中引入(具體信息參考: JEP 317: Experimental Java-Based JIT Compiler),JDK17中移除(移除原因參考: JEP 410: Remove the Experimental AOT and JIT Compiler)

3.2.2 分層編譯

在 Java7 引入了分層編譯,這種方式綜合了 C1 的啟動優勢和 C2 的峰值性能優勢。分層編譯將 JVM 的執行狀態分為5個層次:

  • 第0層:程序解釋執行,默認開啟性能監控(Profiling),如果不開啟,可觸發第二層編譯
  • 第1層:C1編譯,將字節碼編譯成本地代碼,進行簡單可靠的優化,不開啟Profiling
  • 第2層:C1編譯,開啟Profiling,僅執行帶方法調用次數和循環回邊執行次數Profiling的C1編譯
  • 第3層:C1編譯,執行所有帶Profiling的C1編譯
  • 第4層:C2編譯,將字節碼編譯為本地代碼,但會啟用一下編譯耗時較長的優化,甚至會根據性能監控信息進行一些不可靠的激進優化。

Java8 中默認開啟分層編譯,-XX:-TieredCompilation 參數可關閉分層編譯只使用C2編譯,如果只使用C1編譯可設置參數 -XX:TieredStopAtLevel=1。

-Xint參數可設置為強制解釋器模式運行,-Xcomp可設置為強制運行JIT編譯模式。

3.2.3 熱點代碼探測

Hotspot 虛擬機判定熱點代碼基于2種計數器進行,方法調用計數器和回邊計數器,只有代碼符合標準并達到設置的閾值才會進行JIT編譯優化。

1)方法調用計數器

當某個方法調用次數達到閾值就會觸發JIT編譯優化。

jinfo -flag CompileThreshold 或者 java -XX:+PrintFlagsFinal -version 命令可查看方法調用次數閾值,客戶端模式下默認值為1500,服務端模式下默認值為10000。

2)回邊計數器

用于統計方法體中循環體代碼執行次數,字節碼中遇到控制流向后跳轉的指令稱為“回邊”(Back Edge),用于計算是否為熱點代碼的閾值。

計算公式如下:

回邊計數器閾值 = 方法調用計數器閾值(CompileThreshold)*(OSR比率(OnStackReplacePercentage)-解釋器監控比例(InterpreterProfilePercentage))/ 100

java -XX:+PrintFlagsFinal -version 命令可查看相關參數

?根據圖中顯示的各參數的默認值可以計算出回邊計數器閾值為:1000 * (140 - 33) = 10700

3.2.4 編譯優化技術

1)方法內聯

方法內聯的優化行為是將目標方法的代碼復制到發起調用的方法中,避免真實方法調用。

private int add(int a, int b, int c, int d) {return addInt1(a, b) + addInt2(c, d);
}
?
private int addInt1(int a, int b) {return a + b;
}
?
private int addInt2(int a, int b) {return a + b;
}

例如上面的代碼如果被檢測為熱點代碼,則會被優化為以下代碼:

private int add(int a, int b, int c, int d) {return a + b + c + d;
}

熱點方法不一定都會被內聯優化,只有當方法體大小小于參數 -XX:FreqInlineSize 值(默認325字節)才會進行內聯,非熱點方法當方法體小于參數 -XX:MaxInlineSize 值(默認35字節)才會進行內聯。

相關性能調優 :

  • 減小熱點方法檢測閾值,增加內聯方法體閾值,缺點則是會增加內存占用
  • 盡量避免在一個方法體內寫入大量代碼,習慣使用小方法體
  • 盡量使用final private static 關鍵字修飾方法,代碼優化時,因為繼承需要額外的類型檢查。

2)鎖消除

當方法中的局部方法中創建的對象只能被當前線程訪問時,不存在鎖競爭,JIT編譯會對這個對象的方法進行鎖消除。

參數 -XX:+EliminateLocks 可以開啟鎖消除(默認開啟),-XX:-EliminateLocks 則是關閉鎖消除。

3)鎖粗化

如果檢測到同一個對象執行了連續的加鎖和解鎖操作,則會將這一系列操作合并成一個更大的鎖,從而提升程序運行效率。

4)逃逸分析

JIT編譯器會對熱點代碼中的對象進行逃逸分析,分析該對象動態作用域,當被傳遞到其他方法中稱為方法逃逸,當能被外部方法所引用則為線程逃逸

不逃逸 到 方法逃逸 再到 線程逃逸,逃逸程度由低到高。

逃逸分析可以通過參數 -XX:+DoEscapeAnalysis開啟(jdk1.8默認開啟),或 -XX:-DoEscapeAnalysis 關閉。

關閉逃逸分析會導致對象分配到堆中,頻繁觸發垃圾回收導致代碼運行慢。

5)標量替換

當確定對象不會逃逸出線程之外,該對象則會被分配到棧上,對象分配到棧需要進行成員變量拆分,這種優化技術叫做標量替換。標量替換需要開啟逃逸分析。

標量替換可以通過參數 -XX:+EliminateAllocations開啟(jdk1.8默認開啟),或-XX:+EliminateAllocations關閉

3.3 垃圾收集器

Java的一個主要特點就是開發人員不需要過分關注對象的內存管理,無用對象的銷毀和空間釋放都交由JVM的垃圾收集器處理。這減輕了編程負擔提高了編程效率,但垃圾回收也會影響程序的性能。

詳細介紹見上章。

四、總結

JVM中的執行引擎是JVM的重要組成部分之一,主要負責將字節碼指令翻譯成機器碼指令。

執行引擎包括解釋器,JIT解釋器和垃圾收集器。

解釋器就是運行時的“翻譯者”,將字節碼解釋為機器指令。

但是某些頻繁執行的熱點代碼依然采用解釋執行的話會導致程序執行很慢,JIT編譯器則是負責將熱點代碼編譯分層優化成本地機器碼。

垃圾收集器則負責無用對象的銷毀,釋放內存空間。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/895064.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/895064.shtml
英文地址,請注明出處:http://en.pswp.cn/news/895064.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

C++ 順序表

順序表的操作有以下: 1 順序表的元素插入 給定一個索引和元素,這個位置往后的元素位置都要往后移動一次,元素插入的步驟有以下幾步 (1)判斷插入的位置是否合法,如果不合法則拋出異常 (2&…

mysql安裝starting the server報錯

win10家庭版無法啟動服務的,先不要退出,返回上一欄,然后通過電腦搜索欄輸入服務兩個字,在里面找到mysql80,右鍵屬性-登錄,登錄身份切換為本地系統就行了

萬有的函數關係速成2. 連續和導數

1.討論間斷點類型 定義: 若函數在某點不滿足連續的條件,則該點為間斷點。 第一類間斷點是左右極限都存在的間斷點,其中左右極限相等的是可去間斷點,不相等的是跳躍間斷點; 第二類間斷點是左右極限至少有一個不存在的間斷點,包括無窮間斷點(極限為無窮)和振蕩間斷點…

【專題】2025年我國機器人產業發展形勢展望:人形機器人量產及商業化關鍵挑戰報告匯總PDF洞察(附原數據表)

原文鏈接:https://tecdat.cn/?p39668 機器人已廣泛融入我們生活的方方面面。在工業領域,它們宛如不知疲倦的工匠,精準地完成打磨、焊接等精細工作,極大提升了生產效率和產品質量;在日常生活里,它們是貼心…

用docker在本地用open-webui部署網頁版deepseek

前置條件 用Ollama在本地CMD窗口運行deepseek大模型-CSDN博客文章瀏覽閱讀109次,點贊5次,收藏2次。首次運行需要下載deepseek的大模型包(大約5GB,根據本地網速的不同在半個小時到幾個小時之間下載完成) ,并…

android的DataBinding簡介

Android DataBinding 簡介 DataBinding 是 Android Jetpack 中的數據綁定庫,用于將 UI 組件直接與數據模型綁定,減少模板代碼并實現雙向數據同步。它通過聲明式布局簡化 UI 更新邏輯,常用于 MVVM(Model-View-ViewModel&#xff0…

企業如何利用DeepSeek提升網絡安全管理水平

企業可以通過深度整合DeepSeek的AI能力,構建智能化、動態化的網絡安全防御體系,以應對APT(高級持續性威脅)等復雜攻擊。以下是具體策略與實踐路徑: 1. AI驅動的威脅檢測與分析 多模態威脅狩獵 DeepSeek的深度學習技術能…

DeepSeek-R1 云環境搭建部署流程

DeepSeek橫空出世,在國際AI圈備受關注,作為個人開發者,AI的應用可以有效地提高個人開發效率。除此之外,DeepSeek的思考過程、思考能力是開放的,這對我們對結果調優有很好的幫助效果。 DeepSeek是一個基于人工智能技術…

x小兔鮮vue.js

LayoutFooter.vue <template><footer class"app_footer"><!-- 聯系我們 --><div class"contact"><div class"container"><dl><dt>客戶服務</dt><dd><i class"iconfont icon-kef…

磁盤分區損壞:深度解析與數據恢復策略

一、磁盤分區損壞現象概述 磁盤分區損壞是計算機數據存儲領域的一個常見問題&#xff0c;它通常表現為硬盤上的某個分區無法正常訪問&#xff0c;數據讀寫失敗&#xff0c;甚至整個分區消失。這種損壞可能源于多種因素&#xff0c;不僅影響用戶的正常使用&#xff0c;更可能導…

fetch請求總結,fastadmin中后臺接口強制返回json數據

fetch請求 提交圖片,只支持formData方式,這樣會自動變為multiform方式,而且一般的post大多都可以用這樣的方式來完成請求 const formData new FormData(); formData.append(file, fileInput.files[0]); formData.append(pid, id); formData.append(dc, 1);fetch(/api/common…

Python----Python高級(網絡編程:網絡基礎:發展歷程,IP地址,MAC地址,域名,端口,子網掩碼,網關,URL,DHCP,交換機)

一、網絡 早期的計算機程序都是在本機上運行的&#xff0c;數據存儲和處理都在同一臺機器上完成。隨著技術的發展&#xff0c;人 們開始有了讓計算機之間相互通信的需求。例如安裝在個人計算機上的計算器或記事本應用&#xff0c;其運行環 境僅限于個人計算機內部。這種設置雖然…

k8sollama部署deepseek-R1模型,內網無坑

這是目錄 linux下載ollama模型文件下載到本地,打包遷移到k8s等無網絡環境使用下載打包ollama鏡像非k8s環境使用k8s部署訪問方式非ollama運行deepseek模型linux下載ollama 下載后可存放其他服務器 curl -L https://ollama.com/download/ollama-linux-amd64.tgz -o ollama-linu…

機器學習基本概念(附代碼)

這里的“機器”指的是計算機軟硬件組織&#xff0c;而非傳統的機械裝置&#xff1b;而“學習”&#xff0c;則是指軟件通過訓練過程&#xff0c;其性能得以提升的過程。 一、算法與模型的關系 在機器學習領域&#xff0c;算法和模型是兩個核心概念。算法是一種偏抽象的概念&a…

前端開發知識梳理 - HTMLCSS

1. 盒模型 由內容區&#xff08;content&#xff09;、內邊距&#xff08;padding&#xff09;、邊框&#xff08;border&#xff09;和外邊距&#xff08;margin&#xff09;組成。 &#xff08;1&#xff09;標準盒模型&#xff08;box-sizing默認值, content-box&#xff…

.NET周刊【1月第4期 2025-01-26】

國內文章 低成本高可用方案&#xff01;Linux系統下SQL Server數據庫鏡像配置全流程詳解 https://www.cnblogs.com/lyhabc/p/18660810/linux-sql-server-database-mirroring-configuration-guide 本文詳細介紹了如何在Linux系統下配置SQL Server數據庫鏡像&#xff0c;以實現…

Nutz Dao與Spring集成

一、集成方式 1、采用Spring的IOC&#xff0c;但是事務還是采用Nutz自己管理控制&#xff1b; 2、采用Spring的聲明式事務管理控制&#xff1b; 二、IOC 直接依據數據源注入即可 Beanpublic NutDao nutz(DataSource dataSource) {return new NutDao (dataSource);;} 此時N…

利用 Python 爬蟲獲取按關鍵字搜索淘寶商品的完整指南

在電商數據分析和市場研究中&#xff0c;獲取商品的詳細信息是至關重要的一步。淘寶作為中國最大的電商平臺之一&#xff0c;提供了豐富的商品數據。通過 Python 爬蟲技術&#xff0c;我們可以高效地獲取按關鍵字搜索的淘寶商品信息。本文將詳細介紹如何利用 Python 爬蟲技術獲…

白嫖RTX 4090?Stable Diffusion:如何給線稿人物快速上色?

大家都知道&#xff0c;在設計的初期&#xff0c;我們通常會先繪制草圖&#xff0c;然后再進行上色處理&#xff0c;最終才開始進行最終的設計工作。在這個上色的過程中&#xff0c;配色是至關重要的一環。這不僅方便了內部同事的評審&#xff0c;也讓產品方和客戶可以直觀地了…

libdrm移植到arm設備

一、環境資源要求 下載libdrm Index of /libdrm 這邊使用的是2.4.114版本&#xff0c;版本太高對meson版本要求也很高&#xff0c;為了省事用apt安裝meson就不用太高版本了&#xff0c;1.x版本雖然使用makefile編譯方便但是太老&#xff0c;對應用支持不太好。 https://dri…