最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

java運(yùn)行機(jī)制之編譯期、運(yùn)行期和半編譯半解釋性詳解

 更新時(shí)間:2026年06月04日 09:49:39   作者:likerhood  
編程語(yǔ)言一般都分為編譯執(zhí)行和解釋執(zhí)行,編譯是一次性將程序翻譯,然后交給機(jī)器執(zhí)行,這篇文章主要介紹了java運(yùn)行機(jī)制之編譯期、運(yùn)行期和半編譯半解釋性的相關(guān)資料,需要的朋友可以參考下

前言

Java 的生命周期設(shè)計(jì)之所以經(jīng)典,核心在于它采用了 “半編譯,半解釋” 的混合模式。

要真正做到“有深度”地理解 Java 的編譯期和運(yùn)行期,需要深入到 前端編譯(javac后端編譯/執(zhí)行(JIT/JVM) 的底層工作流與優(yōu)化策略中。

如果從程序執(zhí)行模型來(lái)看,編程語(yǔ)言大致可以分為三類(lèi):

  • 純編譯型語(yǔ)言:提前編譯為機(jī)器碼,運(yùn)行速度極快,但跨平臺(tái)能力較差;
  • 純解釋型語(yǔ)言:運(yùn)行時(shí)逐行解釋執(zhí)行,靈活性強(qiáng),但性能較低;
  • 半編譯半解釋型語(yǔ)言:先編譯為中間字節(jié)碼,再由虛擬機(jī)動(dòng)態(tài)執(zhí)行與優(yōu)化。

Java 并不會(huì)像 C/C++ 那樣直接編譯為特定平臺(tái)的機(jī)器碼,而是先通過(guò) javac 編譯器將源碼編譯為 跨平臺(tái)字節(jié)碼(Bytecode),再交由 JVM(Java Virtual Machine)在不同平臺(tái)上運(yùn)行。

在運(yùn)行過(guò)程中,JVM 又結(jié)合了:

  • 解釋執(zhí)行(Interpreter)
  • 即時(shí)編譯(JIT, Just-In-Time Compiler)

兩種機(jī)制。

程序啟動(dòng)初期通過(guò)解釋執(zhí)行保證快速啟動(dòng);而高頻運(yùn)行的熱點(diǎn)代碼,則會(huì)被 JIT 編譯為本地機(jī)器碼并緩存,從而獲得接近 C/C++ 的運(yùn)行性能。

也正因?yàn)槿绱?,Java 才真正實(shí)現(xiàn)了著名的:

Write Once, Run Anywhere(一次編寫(xiě),到處運(yùn)行)

本文從 編譯期、運(yùn)行期、JVM 執(zhí)行機(jī)制、JIT 優(yōu)化以及三種語(yǔ)言執(zhí)行模型 等多個(gè)維度,簡(jiǎn)單梳理 Java 的運(yùn)行機(jī)制與底層原理。

一、 編譯期

Java 的編譯期通常指的是前端編譯,即由 javac 編譯器將 .java 源代碼文件轉(zhuǎn)化為 .class 字節(jié)碼文件的過(guò)程。

這個(gè)階段的核心目標(biāo)是:校驗(yàn)語(yǔ)言規(guī)范、轉(zhuǎn)換語(yǔ)法結(jié)構(gòu),但不做深度的性能優(yōu)化。

1.1 核心機(jī)制

編譯期的主要工作不是優(yōu)化性能,而是將 .java 源碼轉(zhuǎn)換為符合 JVM 規(guī)范的 .class 字節(jié)碼。

javac的運(yùn)行機(jī)制如下

  • 解析與填充符號(hào)表 :

    將源代碼字符流轉(zhuǎn)變?yōu)闃?biāo)記(Token),構(gòu)造出抽象語(yǔ)法樹(shù)(AST)。此時(shí)如果漏掉分號(hào),就會(huì)報(bào)語(yǔ)法錯(cuò)誤。

  • 注解處理 :

    編譯器允許自定義的注解處理器去掃描和修改 AST。

    Lombok 就是在此階段大顯身手,強(qiáng)行插入 getter/setter 節(jié)點(diǎn),隨后編譯器基于修改后的 AST 重新編譯。

  • 語(yǔ)義分析:

    檢查變量是否聲明、類(lèi)型是否匹配。進(jìn)行常量折疊(Constant Folding)(如 int a = 1 + 2; 直接變成 3)。

  • 字節(jié)碼生成與解語(yǔ)法糖

    JVM 不認(rèn)識(shí)語(yǔ)法糖(如增強(qiáng) for、變長(zhǎng)參數(shù)),javac 會(huì)將其還原。

    例如泛型的類(lèi)型擦除(Type Erasure)就在此發(fā)生,List<String> 會(huì)被擦除為 List。

    最終,AST 被轉(zhuǎn)換為字節(jié)碼指令寫(xiě)入 .class 文件。

1.2 方法重載

靜態(tài)類(lèi)型檢查: 編譯器嚴(yán)格按照變量的聲明類(lèi)型進(jìn)行校驗(yàn)。

如果代碼中有多個(gè)同名方法(方法重載 Overload),該調(diào)哪個(gè)?

  • 決策邏輯: 編譯器完全根據(jù)傳入?yún)?shù)的聲明類(lèi)型(靜態(tài)類(lèi)型)來(lái)決定。
  • 結(jié)果: 編譯器一旦匹配到最合適的重載方法,就會(huì)將這個(gè)確定的符號(hào)引用硬編碼寫(xiě)進(jìn) .class 文件的字節(jié)碼中。重載的決斷,在編譯期就已經(jīng)徹底鎖死。
class Animal {}
class Dog extends Animal {}

public class Test {
    // 【方法重載 Overload】
    public void feed(Animal a) { System.out.println("Feeding an animal..."); }
    public void feed(Dog d) { System.out.println("Feeding a dog..."); }

    public static void main(String[] args) {
        // 靜態(tài)類(lèi)型: Animal, 實(shí)際類(lèi)型: Dog
        Animal myPet = new Dog(); 
        Test test = new Test();
        
        // 提問(wèn):這里會(huì)輸出什么?
        test.feed(myPet); 
    }
}

底層執(zhí)行流程:

  1. 編譯期: 編譯器看到 test.feed(myPet)。它檢查 myPet靜態(tài)類(lèi)型(Animal),于是匹配到了 feed(Animal a),并將該符號(hào)引用寫(xiě)入字節(jié)碼。
  2. 運(yùn)行期(實(shí)干家): JVM 執(zhí)行時(shí),看到字節(jié)碼指令要求調(diào)用 feed(Animal a),直接執(zhí)行。它不會(huì)在此刻因?yàn)?myPet 實(shí)際上是個(gè) Dog 而去反悔重選。
  3. 最終輸出: Feeding an animal...

二、 運(yùn)行期

運(yùn)行期是 Java 最為復(fù)雜和體現(xiàn)技術(shù)深度的部分。 當(dāng)類(lèi)加載器將 .class 文件讀入內(nèi)存后,JVM(java虛擬機(jī))開(kāi)始接管一切。

運(yùn)行期(由 JVM 和 JIT 編譯器主導(dǎo))它生存在一個(gè)動(dòng)態(tài)的世界里,眼中只有堆內(nèi)存里等號(hào)右邊的真實(shí)對(duì)象。

2.1 核心機(jī)制

  • 動(dòng)態(tài)類(lèi)加載機(jī)制:
    • 字節(jié)碼被加載進(jìn)方法區(qū)(Metaspace),在“解析”階段,JVM 會(huì)將常量池中的符號(hào)引用替換為直接引用(內(nèi)存指針)。
    • 對(duì)于多態(tài)方法,這個(gè)解析會(huì)推遲到真正運(yùn)行時(shí)才進(jìn)行(動(dòng)態(tài)綁定)。
  • 混合模式 (Interpreter + JIT):
    • 解釋器 (Interpreter):
      • 程序剛啟動(dòng)時(shí),JVM 的解釋器會(huì)逐條讀取字節(jié)碼,將其翻譯成當(dāng)前操作系統(tǒng)認(rèn)識(shí)的機(jī)器碼并執(zhí)行。
      • 作用: 保證程序能瞬間啟動(dòng),不需要等待漫長(zhǎng)的全量編譯時(shí)間。
    • 即時(shí)編譯器 (JIT - Just-In-Time):
      • 性能優(yōu)化關(guān)鍵:當(dāng)它發(fā)現(xiàn)某一段代碼(比如某個(gè)方法、某個(gè)大循環(huán))被極其頻繁地調(diào)用時(shí),它會(huì)把這段代碼標(biāo)記為“熱點(diǎn)代碼(Hot Spot)”。
      • JIT 會(huì)將其編譯為本地機(jī)器碼(C1 編譯器做局部?jī)?yōu)化,C2 編譯器做激進(jìn)優(yōu)化)。
      • 下次再走到這段代碼時(shí),JVM 直接執(zhí)行緩存的機(jī)器碼,速度提升。

2.2 多態(tài)

運(yùn)行期的動(dòng)態(tài)特性開(kāi)始顯現(xiàn):如何實(shí)現(xiàn)多態(tài)(方法重寫(xiě) Override)?

  • 決策邏輯: JVM 無(wú)視變量的聲明類(lèi)型,直接去堆內(nèi)存中找對(duì)象的實(shí)際類(lèi)型。
  • 執(zhí)行過(guò)程: JVM 查該實(shí)際類(lèi)型對(duì)象的虛方法表(vtable)。如果在子類(lèi)中找到了重寫(xiě)的方法,就執(zhí)行子類(lèi)的邏輯;否則順著繼承鏈往上找。這就是 Java 實(shí)現(xiàn)多態(tài)的底層基石。
// 1. 定義頂層父類(lèi)
class Animal {
    public void speak() {
        System.out.println("Animal vtable: [speak() -> Animal.speak()] : 動(dòng)物發(fā)出未知的叫聲");
    }
}

// 2. 定義子類(lèi) Dog:【重寫(xiě)】了 speak 方法
class Dog extends Animal {
    @Override
    public void speak() {
        System.out.println("Dog vtable: [speak() -> Dog.speak()] : 汪汪汪!(執(zhí)行了子類(lèi)邏輯)");
    }
}

// 3. 定義子類(lèi) Bird:【沒(méi)有重寫(xiě)】 speak 方法
class Bird extends Animal {
    public void fly() {
        System.out.println("鳥(niǎo)兒在飛翔...");
    }
    // 注意:這里沒(méi)有重寫(xiě) speak() 方法
}

// 4. 測(cè)試主類(lèi)
public class VTableTest {
    public static void main(String[] args) {
        System.out.println("====== 多態(tài)與虛方法表測(cè)試開(kāi)始 ======\n");

        /* * 場(chǎng)景 :JVM 無(wú)視聲明類(lèi)型 (Animal),直接找實(shí)際類(lèi)型 (Dog)
         */
        Animal myDog = new Dog(); // 聲明類(lèi)型: Animal, 實(shí)際類(lèi)型: Dog
        System.out.print("調(diào)用 myDog.speak() ---> ");
        // JVM 去堆內(nèi)存找 myDog 的實(shí)際對(duì)象頭,查 Dog 類(lèi)的 vtable
        // 在 Dog 類(lèi)的 vtable 中找到了重寫(xiě)的 speak(),直接執(zhí)行!
        myDog.speak(); 

        System.out.println("--------------------------------------------------");

        /* * 場(chǎng)景 :順著繼承鏈往上找
         */
        Animal myBird = new Bird(); // 聲明類(lèi)型: Animal, 實(shí)際類(lèi)型: Bird
        System.out.print("調(diào)用 myBird.speak() ---> ");
        // JVM 去堆內(nèi)存找 myBird 的實(shí)際對(duì)象頭,查 Bird 類(lèi)的 vtable
        // 發(fā)現(xiàn) Bird 類(lèi)并沒(méi)有重寫(xiě) speak(),查表落空!
        // 觸發(fā)機(jī)制:順著繼承鏈往上找,查到 Animal 類(lèi)的 vtable 中有 speak(),執(zhí)行父類(lèi)邏輯!
        myBird.speak(); 

        System.out.println("\n====== 測(cè)試結(jié)束 ======");
    }
}

代碼運(yùn)行時(shí)底層流程:

1. 當(dāng)執(zhí)行 myDog.speak() 時(shí):

  • 編譯期: javac 編譯器只看左邊,確認(rèn) Animal 類(lèi)里確實(shí)有 speak() 方法,于是允許編譯通過(guò),并在字節(jié)碼中寫(xiě)入一條 invokevirtual Animal.speak 的指令。
  • 運(yùn)行期: 執(zhí)行到這條指令時(shí),JVM 的動(dòng)態(tài)特性啟動(dòng)。它根本不管字節(jié)碼里寫(xiě)的是 Animal.speak。它直接去內(nèi)存里找到那個(gè)被 new 出來(lái)的真正對(duì)象(Dog 實(shí)例)。
  • 查表: JVM 提取 Dog 實(shí)例的對(duì)象頭信息,定位到 Dog 類(lèi)的虛方法表(vtable)。它發(fā)現(xiàn)表里的 speak 指針已經(jīng)被替換成了 Dog 自己實(shí)現(xiàn)的方法地址。于是,輸出“汪汪汪”。

2. 當(dāng)執(zhí)行 myBird.speak() 時(shí):

  • 編譯期: 同樣順利通過(guò)。
  • 運(yùn)行期: JVM 找到內(nèi)存里真正的 Bird 實(shí)例。
  • 查表與回溯: JVM 查看 Bird 類(lèi)的虛方法表。但是,因?yàn)?Bird 類(lèi)沒(méi)有寫(xiě) @Override public void speak(),所以在這個(gè)表里,speak 指針依然原封不動(dòng)地指向著父類(lèi) Animalspeak 方法的地址。
  • 結(jié)果: 于是 JVM 只能“順藤摸瓜”,執(zhí)行了父類(lèi)的方法,輸出“動(dòng)物發(fā)出未知的叫聲”。這也就是你提到的:“否則順著繼承鏈往上找”。

三、java代碼的編譯和運(yùn)行

3.1 編譯期:Java 源碼 → 跨平臺(tái)字節(jié)碼

對(duì)應(yīng)圖中綠色區(qū)域,是脫離 JVM 的前置編譯環(huán)節(jié),核心是把人類(lèi)可讀的 Java 源碼,轉(zhuǎn)為 JVM 可識(shí)別的統(tǒng)一標(biāo)準(zhǔn)格式。

  1. 輸入:Java 源碼文件(.java
  2. 核心處理:通過(guò)**javac**等 Java 編譯器完成 4 步標(biāo)準(zhǔn)化操作:
    • 解析源碼生成抽象語(yǔ)法樹(shù)(AST)、填充符號(hào)表
    • 注解處理(如 Lombok 等插件的攔截增強(qiáng))
    • 語(yǔ)義分析(常量折疊、語(yǔ)法校驗(yàn),確保代碼邏輯合法)
    • 生成字節(jié)碼、解語(yǔ)法糖(如 foreach、泛型擦除等簡(jiǎn)化語(yǔ)法的還原)
  3. 輸出:Java 字節(jié)碼文件(.class
    • 關(guān)鍵特性:字節(jié)碼不綁定任何操作系統(tǒng)、CPU 架構(gòu),是 JVM 專(zhuān)屬的跨平臺(tái)統(tǒng)一指令集,是 Java 實(shí)現(xiàn)跨平臺(tái)能力的核心基礎(chǔ)。

3.2 運(yùn)行期:字節(jié)碼 → 機(jī)器碼 → 硬件執(zhí)行

對(duì)應(yīng)圖中紅色 JVM 區(qū)域,是代碼真正執(zhí)行的核心環(huán)節(jié),全流程在 JVM 中完成,最終落地到操作系統(tǒng)和底層硬件。

完整執(zhí)行鏈路如下:

  1. 類(lèi)加載環(huán)節(jié)

    • .class字節(jié)碼通過(guò)文件系統(tǒng) / 網(wǎng)絡(luò)進(jìn)入 JVM,由類(lèi)加載器完成加載→驗(yàn)證→準(zhǔn)備→解析→初始化全流程,將字節(jié)碼加載到 JVM 內(nèi)存中,生成可執(zhí)行的類(lèi)結(jié)構(gòu)。
  2. 混合模式執(zhí)行(JVM 核心設(shè)計(jì))

    • 類(lèi)加載完成后,JVM 采用「解釋執(zhí)行 + JIT 編譯」的雙路徑執(zhí)行,平衡啟動(dòng)速度與峰值性能:

    • 解釋執(zhí)行:由 Java 解釋器逐行翻譯字節(jié)碼為機(jī)器碼,翻譯完成立即執(zhí)行。優(yōu)勢(shì)是啟動(dòng)快、無(wú)編譯等待開(kāi)銷(xiāo),保證跨平臺(tái)兼容性,是程序啟動(dòng)初期的主要執(zhí)行方式。

    • JIT 即時(shí)編譯:運(yùn)行時(shí) JVM 會(huì)識(shí)別高頻執(zhí)行的「熱點(diǎn)代碼」(如循環(huán)、頻繁調(diào)用的方法),由 C1/C2 JIT 編譯器完成深度優(yōu)化(方法內(nèi)聯(lián)、逃逸分析、標(biāo)量替換等),一次性編譯為本地機(jī)器碼并緩存,后續(xù)執(zhí)行直接調(diào)用,無(wú)需重復(fù)翻譯,峰值性能無(wú)限接近 C/C++ 等純編譯型語(yǔ)言。

  3. 最終落地:解釋器 / JIT 生成的機(jī)器碼,交由操作系統(tǒng)調(diào)度,最終在底層 CPU 硬件上完成執(zhí)行。

四、java的語(yǔ)言特性

4.1 純編譯型語(yǔ)言

提前全量靜態(tài)編譯,直接生成目標(biāo)平臺(tái)專(zhuān)屬機(jī)器碼,運(yùn)行時(shí)無(wú)額外翻譯,CPU可直接執(zhí)行,無(wú)中間層開(kāi)銷(xiāo)。

  1. 開(kāi)發(fā)階段:編寫(xiě)源代碼(如C的.c、C++的.cpp文件)。
  2. 全量編譯階段:通過(guò)編譯器(GCC/Clang/MSVC)完成「預(yù)編譯→編譯→匯編→鏈接」,生成當(dāng)前操作系統(tǒng)+CPU架構(gòu)專(zhuān)屬的可執(zhí)行文件(Windows的.exe、Linux的ELF等),內(nèi)含純機(jī)器碼。
  3. 運(yùn)行階段:操作系統(tǒng)直接加載可執(zhí)行文件到內(nèi)存,CPU逐條執(zhí)行機(jī)器碼,全程無(wú)翻譯。

核心優(yōu)缺點(diǎn):

優(yōu)點(diǎn)缺點(diǎn)
運(yùn)行性能最快,無(wú)運(yùn)行時(shí)開(kāi)銷(xiāo)跨平臺(tái)性極差,需按平臺(tái)單獨(dú)編譯
內(nèi)存完全可控,無(wú)額外運(yùn)行時(shí)內(nèi)存占用編譯耗時(shí)久,代碼改動(dòng)需重新編譯
可做極致靜態(tài)編譯優(yōu)化開(kāi)發(fā)門(mén)檻高,需手動(dòng)處理內(nèi)存、指針等底層細(xì)節(jié)

代表語(yǔ)言與適用場(chǎng)景

  • 代表語(yǔ)言:C、C++、Rust、Go、Swift、匯編
  • 適用場(chǎng)景:對(duì)性能、延遲要求極高的領(lǐng)域,如操作系統(tǒng)內(nèi)核、嵌入式開(kāi)發(fā)、游戲引擎、高頻交易系統(tǒng)。

4.2 純解釋型語(yǔ)言

無(wú)提前全量編譯,運(yùn)行時(shí)由解釋器逐行翻譯源代碼為機(jī)器碼并執(zhí)行,不生成獨(dú)立可執(zhí)行文件,也不緩存翻譯結(jié)果,靈活性高但性能犧牲大。

  1. 開(kāi)發(fā)階段:編寫(xiě)源代碼(如早期Python的.py、Shell的.sh文件),直接分發(fā)源碼。
  2. 運(yùn)行階段:目標(biāo)機(jī)器需安裝對(duì)應(yīng)解釋器;解釋器逐行讀取源碼,實(shí)時(shí)翻譯為機(jī)器碼并執(zhí)行,不緩存翻譯結(jié)果。

核心優(yōu)缺點(diǎn)

優(yōu)點(diǎn)缺點(diǎn)
極致源代碼跨平臺(tái),同一份代碼有解釋器即可運(yùn)行運(yùn)行性能極差,通常比純編譯型慢10-100倍
開(kāi)發(fā)效率極高,無(wú)需編譯、改完即跑必須依賴(lài)解釋器,無(wú)對(duì)應(yīng)環(huán)境無(wú)法執(zhí)行
動(dòng)態(tài)性拉滿(mǎn),運(yùn)行時(shí)可隨意修改代碼邏輯、變量類(lèi)型無(wú)法提前靜態(tài)優(yōu)化,運(yùn)行時(shí)才暴露語(yǔ)法、類(lèi)型錯(cuò)誤

代表語(yǔ)言與適用場(chǎng)景

  • 代表語(yǔ)言(經(jīng)典純解釋實(shí)現(xiàn)):早期Python、早期JavaScript、Shell腳本、BASIC
  • 補(bǔ)充說(shuō)明:現(xiàn)代主流腳本語(yǔ)言已脫離純解釋模型(如CPython預(yù)編譯為.pyc、V8引入JIT),本質(zhì)為半編譯半解釋。
  • 適用場(chǎng)景:自動(dòng)化運(yùn)維腳本、快速原型驗(yàn)證、網(wǎng)頁(yè)前端交互、輕量工具開(kāi)發(fā)。

4.3 半編譯半解釋型語(yǔ)言

為解決「編譯型跨平臺(tái)差、解釋型性能差」的矛盾誕生,結(jié)合兩者優(yōu)勢(shì):先通過(guò)前端編譯器將源碼編譯為跨平臺(tái)中間碼(字節(jié)碼),運(yùn)行時(shí)由目標(biāo)平臺(tái)虛擬機(jī)通過(guò)「解釋執(zhí)行+即時(shí)編譯」混合模式轉(zhuǎn)為機(jī)器碼執(zhí)行,實(shí)現(xiàn)“一次編寫(xiě),到處運(yùn)行”。

分為編譯期運(yùn)行期兩大階段:

  1. 編譯期(一次編寫(xiě)的核心)

    • 開(kāi)發(fā)階段:編寫(xiě)Java源代碼(.java文件)。

    • 前端編譯:通過(guò)javac編譯器將源碼一次性編譯為跨平臺(tái)字節(jié)碼文件(.class)。

      • 關(guān)鍵特性:字節(jié)碼不綁定操作系統(tǒng)、CPU架構(gòu),是JVM專(zhuān)屬統(tǒng)一指令集,同一份字節(jié)碼在所有平臺(tái)一致,是跨平臺(tái)核心基礎(chǔ)。
  2. 運(yùn)行期(到處運(yùn)行的核心)

    • 目標(biāo)機(jī)器需安裝對(duì)應(yīng)平臺(tái)的JVM虛擬機(jī)(Windows/Linux/macOS均有專(zhuān)屬JVM,適配底層系統(tǒng)和硬件)。

    • 類(lèi)加載:JVM把.class字節(jié)碼加載到內(nèi)存,完成驗(yàn)證、準(zhǔn)備、解析等流程。

    • 混合模式執(zhí)行(平衡啟動(dòng)速度與峰值性能):

      • 解釋執(zhí)行:程序啟動(dòng)初期,逐行翻譯字節(jié)碼為機(jī)器碼執(zhí)行,保證快速啟動(dòng)與跨平臺(tái)兼容。
      • JIT即時(shí)編譯:運(yùn)行時(shí)識(shí)別高頻「熱點(diǎn)代碼」(如循環(huán)、頻繁調(diào)用的方法),一次性全量編譯為本地機(jī)器碼并緩存,后續(xù)執(zhí)行直接調(diào)用,無(wú)需重復(fù)翻譯,峰值性能無(wú)限接近純編譯型語(yǔ)言。

核心優(yōu)缺點(diǎn)

優(yōu)點(diǎn)缺點(diǎn)
真正跨平臺(tái):同一份字節(jié)碼,有對(duì)應(yīng)JVM即可運(yùn)行,無(wú)需按平臺(tái)修改、重編譯有啟動(dòng)開(kāi)銷(xiāo):JVM啟動(dòng)、類(lèi)加載、解釋執(zhí)行有固定開(kāi)銷(xiāo),不適合超短生命周期程序(如簡(jiǎn)單腳本)
高性能:JIT即時(shí)編譯優(yōu)化,熱點(diǎn)代碼性能接近C/C++,遠(yuǎn)超純解釋型語(yǔ)言強(qiáng)依賴(lài)運(yùn)行環(huán)境:目標(biāo)機(jī)器需安裝對(duì)應(yīng)版本JVM,原生無(wú)法生成獨(dú)立可執(zhí)行文件(GraalVM可實(shí)現(xiàn),非原生能力)
內(nèi)存安全、開(kāi)發(fā)效率高:JVM自帶GC自動(dòng)回收內(nèi)存,無(wú)需手動(dòng)管理,規(guī)避內(nèi)存泄漏、野指針問(wèn)題內(nèi)存占用更高:JVM本身、GC、運(yùn)行時(shí)數(shù)據(jù)區(qū)均有固定內(nèi)存開(kāi)銷(xiāo)
動(dòng)態(tài)能力強(qiáng):基于字節(jié)碼和JVM實(shí)現(xiàn)反射、動(dòng)態(tài)代理,是Spring等企業(yè)級(jí)框架的核心支撐底層控制能力有限:不適合操作系統(tǒng)內(nèi)核、驅(qū)動(dòng)等硬件級(jí)開(kāi)發(fā)

代表語(yǔ)言與適用場(chǎng)景

  • 代表語(yǔ)言:Java、C#、Kotlin(JVM平臺(tái))、Scala
  • 適用場(chǎng)景:企業(yè)級(jí)后端開(kāi)發(fā)、Android開(kāi)發(fā)、大數(shù)據(jù)框架(Hadoop/Spark)、中間件開(kāi)發(fā),是兼顧跨平臺(tái)性、開(kāi)發(fā)效率與高性能的優(yōu)選方案。

4.4 常見(jiàn)誤區(qū)

  1. 現(xiàn)代Python/JavaScript并非純解釋型語(yǔ)言:CPython會(huì)預(yù)編譯為.pyc字節(jié)碼,Chrome V8、PyPy均引入JIT編譯,本質(zhì)已屬于半編譯半解釋模型。
  2. Go/Rust并非半編譯型語(yǔ)言:二者雖帶GC、協(xié)程調(diào)度等運(yùn)行時(shí)能力,但均提前全量編譯為目標(biāo)平臺(tái)機(jī)器碼,運(yùn)行時(shí)無(wú)翻譯環(huán)節(jié),屬于純編譯型語(yǔ)言。
  3. Java并非固定半編譯半解釋模式:現(xiàn)代JVM默認(rèn)「解釋+JIT」混合模式,可通過(guò)參數(shù)強(qiáng)制純解釋/純編譯;GraalVM支持提前將Java代碼編譯為本地機(jī)器碼,轉(zhuǎn)為純編譯型執(zhí)行。

總結(jié)

Java 的運(yùn)行機(jī)制,本質(zhì)上是一套圍繞 “跨平臺(tái) + 高性能” 而設(shè)計(jì)的動(dòng)態(tài)執(zhí)行體系。

與傳統(tǒng)純編譯型語(yǔ)言不同,Java 并不會(huì)直接生成特定平臺(tái)的機(jī)器碼,而是采用:**“源碼 → 字節(jié)碼 → JVM → 機(jī)器碼”**的分層執(zhí)行模型。

它的本質(zhì)是:

先編譯為跨平臺(tái)字節(jié)碼,再由 JVM 動(dòng)態(tài)解釋與 JIT 編譯執(zhí)行。

因此:

  • 編譯型解決性能問(wèn)題
  • 解釋型解決跨平臺(tái)問(wèn)題
  • JVM/JIT 負(fù)責(zé)在兩者之間尋找平衡

最終形成了 Java 最經(jīng)典的設(shè)計(jì)哲學(xué):

一次編寫(xiě),到處運(yùn)行(Write Once, Run Anywhere)

到此這篇關(guān)于java運(yùn)行機(jī)制之編譯期、運(yùn)行期和半編譯半解釋性詳解的文章就介紹到這了,更多相關(guān)java編譯期、運(yùn)行期和半編譯半解釋性?xún)?nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • springboot整合gateway實(shí)現(xiàn)網(wǎng)關(guān)功能的示例代碼

    springboot整合gateway實(shí)現(xiàn)網(wǎng)關(guān)功能的示例代碼

    本文主要介紹了springboot整合gateway實(shí)現(xiàn)網(wǎng)關(guān)功能的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • ThreadLocal內(nèi)存泄露的產(chǎn)生原因和處理方法

    ThreadLocal內(nèi)存泄露的產(chǎn)生原因和處理方法

    ThreadLocal 的內(nèi)存泄漏問(wèn)題通常發(fā)生在使用 ThreadLocal 存儲(chǔ)對(duì)象時(shí),尤其是在多線(xiàn)程環(huán)境中,線(xiàn)程池中的線(xiàn)程復(fù)用可能導(dǎo)致一些資源沒(méi)有及時(shí)清理,從而引發(fā)內(nèi)存泄漏,所以本文給大家介紹了ThreadLocal內(nèi)存泄露的產(chǎn)生原因和處理方法,需要的朋友可以參考下
    2024-12-12
  • Mybatis-Plus使用saveOrUpdate及問(wèn)題解決方法

    Mybatis-Plus使用saveOrUpdate及問(wèn)題解決方法

    本文主要介紹了Mybatis-Plus使用saveOrUpdate及問(wèn)題解決方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-01-01
  • springBoot整合CXF并實(shí)現(xiàn)用戶(hù)名密碼校驗(yàn)的方法

    springBoot整合CXF并實(shí)現(xiàn)用戶(hù)名密碼校驗(yàn)的方法

    這篇文章主要介紹了springBoot整合CXF并實(shí)現(xiàn)用戶(hù)名密碼校驗(yàn)的方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-08-08
  • Java 截取視頻資料中的某一幀作為縮略圖

    Java 截取視頻資料中的某一幀作為縮略圖

    最近項(xiàng)目中有一個(gè)需求,就是Java 截取視頻資料中的某一幀作為縮略圖,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-09-09
  • Java?spring?通過(guò)注解方式創(chuàng)建對(duì)象的示例詳解

    Java?spring?通過(guò)注解方式創(chuàng)建對(duì)象的示例詳解

    這篇文章主要介紹了java?spring?通過(guò)注解方式創(chuàng)建對(duì)象,本文結(jié)合示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-02-02
  • java8中Stream的使用以及分割list案例

    java8中Stream的使用以及分割list案例

    這篇文章主要介紹了java8中Stream的使用以及分割list案例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-08-08
  • Java中的stream流分組示例詳解

    Java中的stream流分組示例詳解

    Java8 Stream API以函數(shù)式風(fēng)格處理集合數(shù)據(jù),支持分組、統(tǒng)計(jì)等操作,可按單/多字段分組,使用String、Map.Entry或Java16 record定義鍵,并獲取數(shù)量、屬性集合、極值等信息,本文給大家介紹Java中的stream流分組,感興趣的朋友跟隨小編一起看看吧
    2025-08-08
  • Nacos客戶(hù)端本地緩存和故障轉(zhuǎn)移方式

    Nacos客戶(hù)端本地緩存和故障轉(zhuǎn)移方式

    Nacos客戶(hù)端在從Server獲得服務(wù)時(shí),若出現(xiàn)故障,會(huì)通過(guò)ServiceInfoHolder和FailoverReactor進(jìn)行故障轉(zhuǎn)移,ServiceInfoHolder緩存服務(wù)信息,FailoverReactor處理故障轉(zhuǎn)移,包括開(kāi)啟故障轉(zhuǎn)移開(kāi)關(guān)、讀取備份文件等
    2024-12-12
  • SpringBoot+Apache tika實(shí)現(xiàn)文檔內(nèi)容解析的示例詳解

    SpringBoot+Apache tika實(shí)現(xiàn)文檔內(nèi)容解析的示例詳解

    Apache tika是Apache開(kāi)源的一個(gè)文檔解析工具,本文主要為大家介紹了如何在springboot中引入tika的方式解析文檔,感興趣的小伙伴可以了解一下
    2023-07-07

最新評(píng)論

绥化市| 卓尼县| 崇明县| 乌鲁木齐县| 札达县| 贵州省| 博兴县| 陆丰市| 精河县| 股票| 永州市| 中山市| 通城县| 衡南县| 海盐县| 来凤县| 湄潭县| 娱乐| 房产| 聂荣县| 夏河县| 苏州市| 阿城市| 潮州市| 成武县| 铜陵市| 琼海市| 伊春市| 敖汉旗| 巴林右旗| 湘潭县| 长兴县| 固阳县| 尼木县| 五指山市| 沂源县| 榆中县| 额敏县| 潍坊市| 公主岭市| 永昌县|