深入理解 Java JVM

文章目錄

    • 📕1. JVM簡介
    • 📕2. JVM運行流程
    • 📕3. JVM運行時數據區
    • 📕4. JVM類加載
        • ??4.1 類加載過程
        • ??4.2 雙親委派模型
        • ??4.3 破壞雙親委派模型
    • 📕5. JVM垃圾回收機制(GC機制)
        • ??5.1 判斷死亡對象的算法
        • ??5.2 垃圾回收算法

📕1. JVM簡介

JVM 是 Java Virtual Machine 的簡稱,意為 Java虛擬機。 虛擬機是指通過軟件模擬的具有完整硬件功能的、運?在?個完全隔離的環境中的完整計算機系統。JVM 是?臺被定制過的現實當中不存在的計算機。

📕2. JVM運行流程

JVM 是 Java 運?的基礎,也是實現?次編譯到處執?的關鍵,那么 JVM 是如何執?的呢?

程序在執?之前先要把java代碼轉換成字節碼(class?件),JVM ?先需要把字節碼通過?定的?式把?件加載到內存中,?字節碼?件是 JVM 的?套指令集規范,并不能直接交個底層操作系統去執?,因此需要特定的命令解析器將字節碼翻譯成底層系統指令再交由CPU去執?,?這個過程中需要調?其他語?的接?來實現整個程序的功能,這就是這4個主要組成部分的職責與功能。
在這里插入圖片描述
總結來看, JVM 主要通過分為以下 4 個部分,來執? Java 程序的,它們分別是:

  1. 類加載器(ClassLoader)
  2. 運?時數據區(Runtime Data Area)
  3. 執?引擎(Execution Engine)
  4. 本地庫接?(Native Interface)

📕3. JVM運行時數據區

JVM 運?時數據區域也叫內存布局,但需要注意的是它和 Java 內存模型((Java Memory Model,簡稱 JMM)完全不同,屬于完全不同的兩個概念,它由以下 5 ?部分組成:
在這里插入圖片描述

🌈 1.

堆的作?:程序中創建的所有對象都在保存在堆中(除了對象的實例屬性外還有對象的頭信息)

在這里插入圖片描述

堆??分為兩個區域:新?代和??代,新?代放新建的對象,當經過?定 GC 次數之后還存活的對象會放???代。新?代還有 3 個區域:?個 Eden + 兩個 Survivor(S0/S1)。

在這里插入圖片描述

垃圾回收的時候會將 Eden 中存活的對象放到?個未使?的 Survivor 中,并把當前的 Endn 和正在使?的Survivor 清除。

🌈 2. 虛擬機棧

Java 虛擬機棧的作?:Java 虛擬機棧的?命周期和線程相同,Java 虛擬機棧描述的是 Java ?法執?的內存模型:每個?法在執?的同時都會創建?個棧幀(Stack Frame)?于存儲局部變量表、操作數棧、動態鏈接、?法出?等信息。咱們常說的堆內存、棧內存中,棧內存指的就是虛擬機棧。

在這里插入圖片描述
通俗來說,棧幀里面包括方法的參數,方法中的局部變量,方法結束后返回值結果,方法結束后跳轉回的地址。

🌈 3. 線程計數器

程序計數器的作?:描述Java程序要運行的下一個字節碼的位置。

程序計數器是?塊?較?的內存空間,可以看做是當前線程所執?的字節碼的?號指?器。

如果當前線程正在執?的是?個Java?法,這個計數器記錄的是正在執?的虛擬機字節碼指令的地址;如果正在執?的是?個Native?法,這個計數器值為空。

🌈 4. 元數據區(Java8之前被稱為方法區)

我們在Java代碼中會創建類,基于類創建對象,創建的對象會有內存空間進行保存,同理類也要有內存空間進行保存。Java中提出了類對象的概念,通過一個特殊的對象,表示一個類的基本信息。在元數據區中,存放的就是類的對應指令。

在元數據區中會保存:
1.類的名字是啥
2.類繼承的父類是啥
3.實現的接口是啥
4.有啥屬性(屬性的名字,類型,限定修飾符)
5.有啥方法(方法的名字,參數列表,返回值,限定修飾符)
6.類靜態成員
7.靜態常量

元數據區的內容Java代碼干預不了,在Java代碼中寫多少類,元數據區的內容就確定了。

🌈 5. 總結

在這里插入圖片描述

📕4. JVM類加載

類加載是JVM從最開始讀取的 .class文件,到最終構造完成類對象的整個過程。是把“類”從硬盤上加載到內存中。

??4.1 類加載過程

對于?個類來說,它的?命周期是這樣的:

在這里插入圖片描述
其中前 5 步是固定的順序并且也是類加載的過程,其中中間的 3 步我們都屬于連接,所以對于類加載來說總共分為以下?個步驟:

  1. 🌈加載

在加載 Loading 階段,Java虛擬機需要完成以下三件事情:

1.通過?個類的全限定類名(包名+類名)來獲取定義此類的?進制字節流
2.將這個字節流所代表的靜態存儲結構轉化為方法區的運?時數據結構。
3.在內存中?成?個代表這個類的Class對象,作為?法區這個類的各種數據的訪問??

  1. 🌈驗證

驗證是連接階段的第?步,校驗上一步讀出來的.class文件是否是合法的。 這?階段的?的是確保Class?件的字節流中包含的信息符合《Java虛擬機規范》的全部約束要求,保證這些信息被當作代碼運?后不會危害虛擬機??的安全。如果驗證過程中發現某個地方的格式出現問題,就需要及時報錯,告知給程序員。

  1. 🌈準備

準備階段是正式為類中定義的變量(即靜態變量,被static修飾的變量)分配內存并設置類變量初始值的階段。此處申請的空間是一個“未初始化”的空間,空間上的每個字節都是0。

//比如此時有這樣一行代碼:
private static int value = 123;
//此時value的值是0,而不是123
  1. 🌈解析

解析過程是針對代碼中的常量進行初始化,也就是把.class文件中的常量也加載到內存中。
對于上述代碼中value,此時value的值就是123了。

  1. 🌈初始化

初始化階段,Java 虛擬機真正開始執?類中編寫的 Java 程序代碼,執?類構造器?法。

??4.2 雙親委派模型

雙親委派模型是用于類加載過程中的第一個環節,根據類的全限定類名(包名+類名)找到對應的.class文件。

🚩什么是雙親委派模型?

如果?個類加載器收到了類加載的請求,它?先不會??去嘗試加載這個類,?是把這個請求委派給?類加載器(每一個類加載器都有一個parent屬性,記錄了自己的父親是誰,這個是無法篡改的,寫死在JVM源碼的)去完成,每?個層次的類加載器都是如此,因此所有的加載請求最終都應該傳送到最頂層的啟動類加載器中,只有當?加載器反饋???法完成這個加載請求(它的搜索范圍中沒有找到所需的類)時,?加載器才會嘗試??去完成加載。

在這里插入圖片描述

JVM自帶了三種類加載器:

  1. Bootstrap ClassLoader :啟動類加載器,負責在Java的標準庫中進行查找
  2. Extension ClassLoader:擴展類加載器,負責在Java的擴展庫中進行查找
  3. Application ClassLoader:應用程序類加載器,負責在Java的第三方庫或者項目中進行查找

在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述

🚩雙親委派模型的優點:

  1. 避免重復加載類:比如 A 類和 B 類都有?個?類 C 類,那么當 A 啟動時就會將 C 類加載起來,那么在 B 類進?加載時就不需要在重復加載 C 類了。
  2. 安全性:使?雙親委派模型也可以保證了 Java 的核? API 不被篡改。比如我自己寫了一個String類,和標準庫的String類正好重復了,此時JVM加載的仍然是標準庫的String類,而不是我寫的String類。保證了安全性。
??4.3 破壞雙親委派模型

雙親委派模型是可以被打破的,程序員在特定的條件下可以實現自己的類加載器,自己實現的類加載器可以讓它遵守雙親委派模型,也可以不遵守雙親委派模型。這種情況會在編寫庫或者框架類代碼時出現,平時我們寫業務代碼并不會遇見。

📕5. JVM垃圾回收機制(GC機制)

上面我們介紹了JVM運行時的數據區,對于程序計數器,虛擬機棧,本地方法棧的生命周期與其對應的線程有關,隨著線程的結束進而銷毀。因此GC主要是回收堆上的對象。在 Java 中,所有的對象都是要存在內存中的(也可以說內存中存儲的是?個個對象),因此我們將內存回收,也可以叫做死亡對象的回收。GC回收并不是以字節為單位進行回收,而是以對象為單位進行回收。

??5.1 判斷死亡對象的算法
  1. 🚩 引用計數算法

給對象增加?個引?計數器,每當有?個地?引?它時,計數器就+1;當引?失效時,計數器就-1;
任何時刻計數器為0的對象就是不能再被使?的,即對象已"死"。

引?計數法實現簡單,判定效率也?較?,在?部分情況下都是?個不錯的算法。?如Python語?就
采?引?計數法進?內存管理。

但是,引入計數算法有兩個弊端:

a) 消耗額外的空間大 : 假如對象只有4字節,計數器有2字節,額外浪費50%的內存空間,造成內存浪費。

b) 循環引用問題 :

在這里插入圖片描述

  1. 🚩可達性分析算法(Java所使用的方案)

此算法的核?思想為 : 通過?系列稱為"GC Roots"的對象作為起始點,從這些節點開始向下搜索,搜
索?過的路徑稱之為"引?鏈",當?個對象到GC Roots沒有任何的引?鏈相連時(從GC Roots到這個對
象不可達)時,證明此對象是不可?的。以下圖為例:

在這里插入圖片描述

對象Object5-Object7之間雖然彼此還有關聯,但是它們到GC Roots是不可達的,因此他們會被判定為可回收對象。

在Java語?中,可作為GC Roots的對象包含下??種:

  1. 虛擬機棧(棧幀中的本地變量表)中引?的對象
  2. ?法區中類靜態屬性引?的對象
  3. ?法區中常量引?的對象
  4. 本地?法棧中 JNI(Native?法)引?的對象
??5.2 垃圾回收算法
  1. 🚩標記-清除算法

“標記-清除"算法是最基礎的收集算法。算法分為"標記"和"清除"兩個階段 : ?先標記出所有需要回收的對象,在標記完成后統?回收所有被標記的對象。后續的收集算法都是基于這種思路并對其不?加以改進?已。

"標記-清除"算法的不?主要有兩個 :

  1. 效率問題:標記(標記就是可達性分析找到碎片的過程)和清除(直接釋放這部分的內存)這兩個過程的效率都不?
  2. 空間問題:標記清除后會產??量不連續的內存碎?,空間碎?太多可能會導致以后在程序運?中需要分配較?對象時,?法找到?夠連續內存?不得不提前觸發另?次垃圾收集。

在這里插入圖片描述

  1. 🚩復制算法

"復制"算法是為了解決"標記-清理"的效率問題。它將可?內存按容量劃分為??相等的兩塊,每次只使?其中的?塊。當這塊內存需要進?垃圾回收時,會將此區域還存活著的對象復制到另?塊上?,然后再把已經使?過的內存區域?次清理掉。這樣做的好處是每次都是對整個半區進?內存回收,內存分配時也就不需要考慮內存碎?等復雜情況,只需要移動堆頂指針,按順序分配即可。此算法實現簡單,運??效。算法的執?流程如下圖 :
在這里插入圖片描述

復制算法很好的解決了內存碎片問題,但仍然存在兩個弊端:

  1. 內存浪費比較多
  2. 如果存活的對象比較多,復制的開銷會非常大
  1. 🚩標記-整理算法

這個方案類似于順序表刪除元素(我們會采用搬運元素的方法),這個方案雖然能解決內存碎片問題,也能避免復制算法的內存浪費,但是,搬運對象的成本也是比較高的。

在這里插入圖片描述

  1. 🚩分代算法

分代算法和上?講的 3 種算法不同,分代算法是通過區域劃分,實現不同區域和不同的垃圾回收策略,從?實現更好的垃圾回收。這就好?中國的?國兩制?針?樣,對于不同的情況和地域設置更符合當地的規則,從?實現更好的管理,這就是分代算法的設計思想。

當前 JVM 垃圾收集都采?的是"分代收集(Generational Collection)"算法,這個算法并沒有新思想,只是根據對象存活周期的不同將內存劃分為?塊。?般是把Java堆分為新?代和?年代。在新?代中,每次垃圾回收都有?批對象死去,只有少量存活,因此我們采?復制算法;??年代中對象存活率?、沒有額外空間對它進?分配擔保,就必須采?"標記-清理"或者"標記-整理"算法

我們將整個堆空間,分為新生代和老生代。新?代中98%的對象都是"朝??死"的,所以并不需要按照1 : 1的?例來劃分內存空間,?是將內存(新?代內存)分為?塊較?的Eden(伊甸園)空間和兩塊較?的Survivor(幸存者)空間,每次使?Eden和其中?塊Survivor(兩個Survivor區域?個稱為From區,另?個稱為To區域)。當回收時,將Eden和Survivor中還存活的對象?次性復制到另?塊Survivor空間上,最后清理掉Eden和剛才?過的Survivor空間。當Survivor空間不夠?時,需要依賴其他內存(?年代)進?分配擔保。

HotSpot默認Eden與Survivor的???例是8 : 1,也就是說Eden:Survivor From : Survivor To =8:1:1

HotSpot實現的復制算法流程如下:

  1. 當Eden區滿的時候,會觸發第?次Minor gc,把還活著的對象拷?到Survivor From區;當Eden區再
    次觸發Minor gc的時候,會掃描Eden區和From區域,對兩個區域進?垃圾回收,經過這次回收后還存
    活的對象,則直接復制到To區域,并將Eden和From區域清空。
  2. 當后續Eden?發?Minor gc的時候,會對Eden和To區域進?垃圾回收,存活的對象復制到From區域,
    并將Eden和To區域清空。
  3. 部分對象會在From和To區域中復制來復制去,如此交換15次(由JVM參數MaxTenuringThreshold決
    定,這個參數默認是15),最終如果還是存活,就存?到?年代

哪些對象會進?新?代?哪些對象會進??年代?

? 新?代:?般創建的對象都會進?新?代;
? ?年代:?對象和經歷了 N 次(?般情況默認是 15 次)垃圾回收依然存活下來的對象會從新?代
移動到?年代。

🌰舉個例子:

在這里插入圖片描述
當我們投簡歷時,簡歷會進入伊甸區,此時會收到非常多的簡歷。但是只有少數簡歷會經過挑選進入面試(從伊甸區進去幸存區),每一輪面試都會淘汰掉很多人,每次進入一輪面試就相當于存活過一輪GC,進入幸存區,當我們經過所有的面試拿到offer進入公司,就意味著我們進入了老生代。但是進入公司后也會有年終考核之類的評比,不過是考核時間長了。但是也有一類人能量非常強大,不用面試直接就能進入公司入職。

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

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

相關文章

Linux內核高效之道:Slab分配器與task_struct緩存管理

前言 在Linux內核中,進程創建與銷毀是最頻繁的操作之一。想象一下:當系統每秒需要處理成百上千次fork()和exit()調用時,如何保證task_struct(進程描述符)的分配與釋放既快速又不產生內存碎片?這就是Slab分配…

雙esp8266-01之間UDP透傳傳輸,自定義協議

使用AT模式的透傳,串口打印的數據包含pd1,4,數據打印的數據不是直接將數據打印出來,包含了pd1,4,特殊字符,針對想要直接開機直接透傳,打印數據且按照自主協議幀頭的功能進行開發。1.server程序:/*************SERVER**…

BGP 路由優選屬性(7)【MED】官方考試綜合實驗題【bgp】【acl】【ip-prefix】【route-policy】【icmp 環路】精講

目錄 一、MED 屬性介紹 二、實驗 2.1 實驗目的 2.2 拓撲圖 2.2 實驗說明 2.3 配置腳本 2.4 驗證配置 2.5 問題分析 2.7 題目需求解析 2.8 場景 1:只允許在 AS12 上操作 2.9 場景 2:只允許在 AS34 上操作 正文 一、MED 屬性介紹 MED 全稱 mu…

html-初級標簽

一.瀏覽器能識別的標簽 1.1 head標簽里的編碼和title <head><meta charset"UTF-8"><title>Title</title> </head>1.2 標題 <body><h1>Welcome to my website</h1><h2>Welcome to my website</h2><…

【八股消消樂】Kafka集群 full GC 解決方案

&#x1f60a;你好&#xff0c;我是小航&#xff0c;一個正在變禿、變強的文藝傾年。 &#x1f514;本專欄《八股消消樂》旨在記錄個人所背的八股文&#xff0c;包括Java/Go開發、Vue開發、系統架構、大模型開發、具身智能、機器學習、深度學習、力扣算法等相關知識點&#xff…

《Java Web程序設計》實驗報告二 學習使用HTML標簽、表格、表單

目 錄 一、實驗目的 二、實驗環境 三、實驗步驟和內容 1、小組成員分工&#xff08;共計4人&#xff09; 2、實驗方案 3、實驗結果與分析 4、項目任務評價 四、遇到的問題和解決方法 五、實驗總結 一、實驗目的 1、HTML基礎知識、基本概念 2、使用HTML標簽、表格進行…

jenkins使用Jenkinsfile部署springboot+docker項目

文章目錄前言一、前期準備二、編輯構建文件二、Jenkins構建總結前言 前面使用Jenkinsfile部署了前端vue項目&#xff0c;接著學習Jenkinsfile部署springboot項目。 一、前期準備 已經安裝好centos,并且安裝了jenkins和docker。本地新建springboot并上傳到gitee上。 二、編輯…

使用ESM3蛋白質語言模型進行快速大規模結構預測

文章目錄ESM3介紹ESM3在線使用本地使用api批量預測ESM相較于AlphaFold的優勢ESM3介紹 ESM3是由EvolutionaryScale&#xff08;前Meta團隊&#xff09;開發的一款蛋白質大語言模型&#xff0c;于2025年以《用語言模型模擬 5 億年的進化》為題正式發表在Science上 文章鏈接: htt…

PostgreSQL 時間/日期管理詳解

PostgreSQL 時間/日期管理詳解 引言 PostgreSQL是一款功能強大的開源關系型數據庫管理系統&#xff0c;在時間/日期管理方面具有獨特的優勢。本文將詳細介紹PostgreSQL中時間/日期數據類型及其相關功能&#xff0c;幫助讀者更好地理解和應用時間/日期管理。 時間/日期數據類型 …

Agent篇

Agent包含哪些模塊&#xff0c;實現了什么功能Agent 就像一個多功能的接口&#xff0c;它能夠接觸并使用一套工具。根據用戶的輸入&#xff0c;Agent會規劃出一條解決用戶問題的路線&#xff0c;決定其中需要調用哪些工具&#xff0c;并調用這些工具。Agent 大語言模型規劃記憶…

利用 MySQL 進行數據清洗

利用 MySQL 進行數據清洗是數據預處理的重要環節&#xff0c;以下是常見的數據清洗操作及對應 SQL 示例&#xff1a;1. 去除重復數據使用 ROW_NUMBER() 或 GROUP BY 識別并刪除重復記錄。-- 查找重復記錄&#xff08;以 user_id 和 email 為例&#xff09; WITH Duplicates AS …

【MySQL筆記】事務的ACID特性與隔離級別

目錄1. 什么是事務&#xff1f;2. 事務的ACID特性&#xff08;重要&#xff09;3. 事務控制語法4. 隔離級別與并發問題1. 什么是事務&#xff1f; 事務&#xff08;Transaction&#xff09;是由一組SQL語句組成的邏輯單元&#xff0c;這些操作要么全部成功&#xff0c;要么全部…

Mock 數據的生成與使用全景詳解

Mock 數據的生成與使用全景詳解 在后端開發過程中,真實數據往往受限于業務進度、隱私保護或接口未完成等因素,無法及時獲取。這時,Mock數據(模擬數據)就成為開發、測試、聯調不可或缺的利器。本文將從Mock數據的意義、常用場景、主流工具、實戰案例到最佳實踐,帶你全面掌…

HTML 標題標簽

需求&#xff1a;在網頁顯示六級標題標簽。代碼&#xff1a;//需求&#xff1a;在網頁顯示六級標題標簽。 <!DOCTYPE html> <html><head><meta charset"utf-8" /><title></title></head><body><h1>一級標題&l…

(限免!!!)全國青少年信息素養大賽-算法創意實踐挑戰賽小學組復賽(代碼版)

選擇題部分在 C 中&#xff0c;以下代表布爾類型的是&#xff08;  &#xff09;選項&#xff1a;A. double B. bool C. int D. char答案&#xff1a;B解析&#xff1a;C 中布爾類型的關鍵字為bool&#xff0c;用于存儲邏輯值true或false。執行以下程序&#xff0c;輸出的…

編譯器優化——LLVM IR,零基礎入門

編譯器優化——LLVM IR&#xff0c;零基礎入門 對于大多數C開發者而言&#xff0c;我們的代碼從人類可讀的文本到機器可執行的二進制文件&#xff0c;中間經歷的過程如同一個黑箱。我們依賴編譯器&#xff08;如GCC, Clang, MSVC&#xff09;來完成這項復雜的轉換。然而&#x…

react中為啥使用剪頭函數

在 React 中使用箭頭函數&#xff08;>&#xff09;主要有以下幾個原因&#xff1a;1. 自動綁定 this傳統函數的問題&#xff1a;在類組件中&#xff0c;普通函數的this指向會根據調用方式變化&#xff0c;導致在事件處理函數中無法正確訪問組件實例&#xff08;this為undef…

JavaSE-多態

多態的概念在完成某個行為時&#xff0c;不同的對象在完成時會呈現出不同的狀態。比如&#xff1a;動物都會吃飯&#xff0c;而貓和狗都是動物&#xff0c;貓在完成吃飯行為時吃貓糧&#xff0c;狗在完成吃飯行為時吃狗糧&#xff0c;貓和狗都會叫&#xff0c;狗在完成這個行為…

TDengine 使用最佳實踐(2)

TDengine 使用最佳實踐&#xff08;1&#xff09; 安裝部署 目錄規劃 軟件安裝 參數配置 時鐘同步 驗證環境 集群部署 寫入查詢 連接方式 數據寫入 數據查詢 運維巡檢 運維規范 數據庫啟停 狀態檢查 運維技巧 日常巡檢 數據庫升級 故障排查 故障定位 日志調試 故障反饋 關于 T…

如何通過公網IP訪問部署在kubernetes中的服務?

背景說明我們有些私有化部署的項目&#xff0c;使用k8s來承載服務&#xff0c;通過ingress-nginx轉發外部的請求到集群。有時候業主的域名沒有申請下來&#xff0c;我們會配置臨時的域名&#xff0c;測試同事配置主機hosts來完成功能驗證&#xff0c;等功能驗證完畢后&#xff…