你編寫的Java代碼是咋跑起來的?

来源:https://www.cnblogs.com/wupeixuan/archive/2019/11/04/11790091.html
-Advertisement-
Play Games

如果你是一名 Java 開發人員,你肯定指定 Java 代碼有很多種不同的運行方式。比如說可以在開發工具(IDEA、Eclipse等)中運行,可以雙擊執行 jar 文件運行,也可以在命令行中運行,甚至可以在網頁(比如各種 OJ)中運行。當然,這些執行方式都離不開 JRE(Java 運行時環境)。 J ...


如果你是一名 Java 開發人員,你肯定指定 Java 代碼有很多種不同的運行方式。比如說可以在開發工具(IDEA、Eclipse等)中運行,可以雙擊執行 jar 文件運行,也可以在命令行中運行,甚至可以在網頁(比如各種 OJ)中運行。當然,這些執行方式都離不開 JRE(Java 運行時環境)。

JRE 包含運行 Java 程式的必需組件,包括 JVM(Java 虛擬機)以及 Java 核心類庫等。Java 程式員經常接觸到的 JDK(Java 開發工具包)同樣包含了 JRE,並且還附帶了一系列開發、診斷工具。

本篇文章主要針對以下兩個問題和大家一起探討:

  1. 為什麼需要 JVM?
  2. JVM 是怎樣運行 Java 代碼的呢?

為什麼需要 JVM?

Java 的一個非常重要的特點就是與平臺的無關性,而使用 JVM 是實現這一特點的關鍵。Java 作為一門高級程式語言,語法複雜,抽象程度高。因此,直接在硬體上運行這種複雜的程式並不現實。所以在運行 Java 程式之前,我們需要對其進行轉換。

設計一個面向 Java 語言特性的虛擬機,並通過編譯器將 Java 程式轉換成該虛擬機所能識別的指令序列(因為 Java 位元組碼指令的操作碼(opcode)被固定為一個位元組,故又稱 Java 位元組碼)。

JVM 一般是在各個現有平臺(如 Windows、Linux)上提供軟體實現,這樣可以使一旦一個程式被轉換成 Java 位元組碼,那麼便可以在不同平臺上的虛擬機實現里運行(一次編寫,到處運行)。

JVM 另外一個好處是帶有托管環境(Managed Runtime),托管環境能夠代替處理一些代碼中冗長而且容易出錯的部分,其中包括自動記憶體管理與垃圾回收(GC)。

另外,托管環境還提供了諸如數組越界、動態類型、安全許可權等等的動態檢測,使我們免於書寫這些無關業務邏輯的代碼。

JVM 是怎樣運行 Java 代碼的呢?

JVM 具體是怎麼運行 Java 位元組碼的呢?下麵我們一起來看一下:

從 JVM 來看,執行 Java 代碼首先需要將它編譯而成的 class 文件載入到 JVM 中。載入後的 Java 類會被存放於方法區(Method Area)中。實際運行時,JVM 會執行方法區內的代碼。

JVM 會在記憶體中劃分出堆和棧來存儲運行時數據,JVM 會將棧細分為面向 Java 方法的 Java 方法棧,面向本地方法(用 C++ 寫的 native 方法)的本地方法棧,以及存放各個線程執行位置的 PC 寄存器。

在運行過程中,每當調用進入一個 Java 方法,JVM 會在當前線程的 Java 方法棧中生成一個棧幀,用以存放局部變數以及位元組碼的操作數。棧幀的大小是提前計算好的,而且 JVM 不要求棧幀在記憶體空間里連續分佈。

當退出當前執行的方法時,不管是正常返回還是異常返回,JVM 均會彈出當前線程的當前棧幀,並將之捨棄。

從硬體視角來看,Java 位元組碼無法直接執行。因此,JVM 需要將位元組碼翻譯成機器碼。

在 HotSpot 裡面,上述翻譯過程有兩種形式:第一種是解釋執行(interpreter),即逐條將位元組碼翻譯成機器碼並執行;第二種是即時編譯(Just-In-Time compilation,JIT),即將一個方法中包含的所有位元組碼編譯成機器碼後再執行。

前者的優勢在於無需等待編譯,而後者的優勢在於實際運行速度更快。HotSpot 預設採用混合模式,綜合瞭解釋執行和即時編譯兩者的優點。它會先解釋執行位元組碼,而後將其中反覆執行的熱點代碼,以方法為單位進行即時編譯。

整個 Java 代碼執行過程如下:

  1. 使用 javac 把 .java 源文件編譯為位元組碼(文件尾碼名為 .class)
  2. 位元組碼經過 JIT 環境變數進行判斷,是否屬於熱點代碼(多次調用的方法或迴圈體)
  3. 熱點代碼使用 JIT 編譯為可執行的機器碼
  4. 非熱點代碼使用解釋器解釋執行所有位元組碼

其中,在運行過程中會被即時編譯的熱點代碼有兩類:

  1. 被多次調用的方法
  2. 被多次執行的迴圈體

針對第一類,編譯器會將整個方法作為編譯對象,這也是標準的 JIT 編譯方式。對於第二類是由迴圈體出發的,但是編譯器依然會以整個方法作為編譯對象,因為發生在方法執行過程中,稱為棧上替換。

HotSpot 採用了多種技術來提升啟動性能以及峰值性能,剛剛提到的即時編譯便是其中最重要的技術之一。

即時編譯建立在程式符合二八定律的假設上,也就是百分之二十的代碼占據了百分之八十的計算資源。

對於占據大部分的不常用的代碼,我們無需耗費時間將其編譯成機器碼,而是採取解釋執行的方式運行;另一方面,對於僅占據小部分的熱點代碼,我們則可以將其編譯成機器碼,以達到理想的運行速度。

為了滿足不同用戶場景的需要,HotSpot 內置了多個即時編譯器:C1、C2。之所以引入多個即時編譯器,是為了在編譯時間和生成代碼的執行效率之間進行取捨。

  • C1 (Client 編譯器)面向的是對啟動性能有要求的客戶端 GUI 程式,採用的優化手段相對簡單,因此編譯時間較短。
  • C2 (Server 編譯器)面向的是對峰值性能有要求的伺服器端程式,採用的優化手段相對複雜,因此編譯時間較長,但同時生成代碼的執行效率較高。

從 Java 7 開始,HotSpot 預設採用分層編譯的方式:熱點方法首先會被 C1 編譯,而後熱點方法中的熱點會進一步被 C2 編譯。

為了不幹擾應用的正常運行,HotSpot 的即時編譯是放在額外的編譯線程中進行的。HotSpot 會根據 CPU 的數量設置編譯線程的數目,並且按 1:2 的比例配置給 C1 及 C2 編譯器。

在計算資源充足的情況下,位元組碼的解釋執行和即時編譯可同時進行。編譯完成後的機器碼會在下次調用該方法時啟用,以替換原本的解釋執行。

其中判斷一段代碼是否為熱點代碼,是不是需要觸發即時編譯,這樣的行為稱為熱點探測(Hot Spot Detection),探測演算法有兩種:

  1. 基於採樣的熱點探測(Sample Based Hot Spot Detection):虛擬機會周期的對各個線程棧頂進行檢查,如果某些方法經常出現在棧頂,這個方法就是熱點方法。優點是實現簡單、高效,很容易獲取方法調用關係。缺點是很難確認方法的 reduce,容易受到線程阻塞或其他外因擾亂。
  2. 基於計數器的熱點探測(Counter Based Hot Spot Detection):為每個方法(甚至是代碼塊)建立計數器,執行次數超過閾值就認為是熱點方法。優點是統計結果精確嚴謹。缺點是實現麻煩,不能直接獲取方法的調用關係。

HotSpot 使用的是第二種-基於計數器的熱點探測,並且有兩類計數器:方法調用計數器(Invocation Counter)和回邊計數器(Back Edge Counter)。

總結

這篇文章主要介紹了為什麼需要 JVM 以及 JVM 是怎樣運行 Java 代碼的。

為什麼需要 JVM:

  1. 提供了可移植性。一次編譯,到處執行。
  2. 提供了代碼托管的環境,代替處理部分冗長而且容易出錯的部分。

JVM 將運行時記憶體區域劃分為五個部分,分別為方法區、堆、PC 寄存器、Java 方法棧和本地方法棧。Java 程式編譯而成的 class 文件,需要先載入至方法區中,方能在 JVM 中運行。

為了提高運行效率,HotSpot 虛擬機採用的是一種混合執行的策略,會解釋執行 Java 位元組碼,然後會將其中反覆執行的熱點代碼,以方法為單位進行即時編譯,翻譯成機器碼後直接運行在底層硬體之上。

HotSpot 裝載了多個不同的即時編譯器,以便在編譯時間和生成代碼的執行效率之間做取捨。

判斷熱點代碼的探測演算法包括基於採樣和基於計數器兩種,HotSpot 採用基於計數器的熱點探測,計數器又分為方法調用計數器和回邊計數器。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • css背景 1. 背景顏色 banckground clor屬性定義元素的背景顏色 ~~~ background color:顏色值; ~~~ 一般情況下元素的背景顏色預設值是transparent(透明的) 2. 背景圖片 background image屬性描述了元素的背景圖像。實際開發常見於L ...
  • [TOC] 不知道這個小知識點用得多不多,曾經在書上看到過,所以有一些印象,前段時間順手寫出類似如下的代碼 斷點調試之後發現無論如何都不相等,方法parseInt()返回的結果確實是NaN,但是與右側的NaN比較返回的結果卻是false,這時候才突然想起來NaN有不等於自身的特性,所以簡單收集一下資 ...
  • 過濾器的基本使用 定義一個過濾器 過濾器可以使用多個· 下麵js代碼的HTML部分 定義一個私有過濾器和私有指令 javascript // 如何自定義一個私有的過濾器(局部) var vm2 = new Vue({ el: ' app2', data: { dt: new Date() }, me ...
  • 前言 在上一篇中,我們對平時進行vue開發中遇到的常用指令進行歸類說明講解,大概已經學會了怎麼去實現數據綁定,以及實現動態的實現數據展示功能,運用指令,可以更好更快的進行開發。而在這一篇中,我們將通過實例,探究vue的生命周期。 萬物皆有靈,世間萬物都擁有靈魂,小到山河湖海,花草樹木,螞蟻到人類,以 ...
  • 前言 2019年6月中旬,實在厭倦了之前平平淡淡的工作和毫不起眼的薪資,不顧親人的反對,毅然決然地決定隻身前往沿海城市,想著找到一份更加具有挑戰性的工作,來徹徹底底地重新打磨自己,同時去追求更好的薪資待遇。當然在此之前,自己每天下班後都會利用業餘時間抓緊複習鞏固刷題等等,大概從3月份開始的吧,持續了 ...
  • 2019/11/2 1、 表現層狀態轉換(REST, representational state transfer.)一種萬維網軟體架構風格,目的是便於不同軟體/程式在網路(例如互聯網)中互相傳遞信息。表現層狀態轉換是根基於超文本傳輸協議(HTTP)之上而確定的一組約束和屬性,是一種設計提供萬維網 ...
  • 前段時間公司根據要求需要將聚石塔上伺服器從杭州整體遷移到張家口,剛好趁這次機會將這些亂七八糟的伺服器做一次梳理和整合,斷斷續續一個月遷移完 成大概優化掉了1/3的機器,完成之後遇到了一些問題,比如曾今零零散散部署在生產上一些可視化UI:apollo,kibana,grafana,jenkins 等等 ...
  • Java 控制台輸入流 System.in和Scanner System.out 是常用的在控制台輸出數據的 System.in 可以從控制台輸入數據 步驟 1 : System.in package stream; import java.io.IOException; import java.i ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...