久久精品精选,精品九九视频,www久久只有这里有精品,亚洲熟女乱色综合一区
    分享

    簡述JVM(1)——類加載器和運行時數據區

     KookNut39 2021-12-15

    大家好,我是KookNut39也是Tommy,在CSDN寫文,寫Java時候我是Tommy,分享一些自己認為在學習過程中比較重要的東西,致力于幫助初學者入門,希望可以幫助你進步。感興趣的歡迎關注博主,和博主一起學習Java知識。大家還可以去專欄查看之前的文章,希望未來能和大家共同探討技術。

    文章目錄

    了解JVM(Java虛擬機)首先我們必須了解VM(虛擬機)是什么。

    所謂虛擬機(Virtual Machine),就是一臺虛擬的計算機。它是一款軟件,用來執行一系列虛擬計算機指令。大體上,虛擬機可以分為系統虛擬機和程序虛擬機。

    我們經常見到的 VMware 就屬于系統虛擬機,它是完全對物理計算機的仿真,提供了一個可運行完整操作系統的軟件平臺。

    程序虛擬機典型的代表就是 Java 虛擬機了,它專門為執行某個單個計算機程序而設計。在 Java 虛擬機中執行的指令我們稱為 Java 字節碼指令。無論是系統虛擬機還是程序虛擬機,在上面運行的軟件都被限制于虛擬機提供的資源。Java 虛擬機是一種執行 Java 字節碼文件的虛擬計算機,它擁有獨立的運行機制。

    Java 技術的核心就是 Java 虛擬機,因為所有的 Java 程序都運行在 Java 虛擬機內部。

    JVM概述

    JVM就是Java虛擬機,虛擬機就是一臺虛擬的計算機,是一款軟件。Java 虛擬機就是二進制字節碼的運行環境,負責裝載字節碼到其內部,解釋或編譯為對應平臺上的機器碼指令執行,每一條 Java 指令,Java 虛擬機中都有詳細定義,如怎么取操作數,怎么處理操作數,處理結果放在哪兒等。JVM是運行在操作系統上的,不與硬件直接交互。

    JVM整體的四個部分

    JVM整體組成可以分為4個部分:

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

    程序在執行之前先要把 Java 代碼轉換成字節碼(.class 文件),JVM 首先需要把字節碼通過一定的類加載器(Class Loader)把文件加載到內存中運行時數據區(Runtime Data Area),而字節碼文件是 JVM 的一套指令集規范,并不能直接交給底層操作系統去執行,因此需要特定的命令解析器(執行引擎(Execution Engine)) 將字節碼翻譯成底層系統指令再交由 CPU 去執行,而這個過程中需要調用其他語言的接口(本地方法接口(Native Interface)) 來實現。整個程序的功能,這就是這 4 個主要組成部分的職責與功能。

    1.1 類加載器

    Java編譯器會為虛擬機轉換源指令。虛擬機代碼存儲在以 .class 為擴展名的類文件中,每個類文件都包含某個類或者接口的定義和實現代碼。

    ? ——Java核心基礎(卷二)

    1.1.1 類加載器過程

    類加載器子系統負責從文件系統或者網絡中加載 class 文件, class 文件在文件開頭有特定的文件標識(字節碼文件都以 CA FE BA BE 標識開頭)。classLoader 只負責 class 文件的加載,至于它是否可以運行,則由執行引擎決定。加載的類信息存放于一塊稱為方法區的內存空間。除了類的信息外,方法區中還會存放運行時常量池信息,可能還包括字符串字面量和數字常量(這部分常量信息是 class 文件中常量池部分的內存映射)。

    類加載的過程

    [外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-XZGhPUyU-1631455118241)(C:\Users\DELL\AppData\Roaming\Typora\typora-user-images\1631431133481.png)]

    1.加載過程是把class文件(字節碼文件)加載到內存中(I/O讀寫)。類加載器把文件加載到內存中,會為每個類創建一個Class類的對象,調用Class類中的方法獲取類的相關信息。

    2.驗證是檢驗加載的類是否有正確的內部結構并和其他類協調一致。

    3.準備階段為類的靜態屬性分配內存,并設置默認初始值(不包含final修飾的static常量),也不會給實例變量初始化。

    4.解析是將二進制數據中的符號引用替換成直接引用(符號引用是用一組符號描述所引用的目標;直接引用是指向目標的指針)。

    5.類初始化

    ? 5.1 什么時候初始化類

    ? 1 )創建類的實例,也就是 new 一個對象
    ? 2)訪問某個類或接口的靜態變量,或者對該靜態變量賦值
    ? 3)調用類的靜態方法
    ? 4)反射
    ? 5)初始化一個類的子類(會首先初始化子類的父類)

    ? 5.2 類的初始化順序:

    ? 父類static --> 子類static --> 父類構造方法 --> 子類構造方法

    1.1.2類加載器的分類

    1.1.2.1啟動類加載器(引導類加載器)

    是由c/c++實現,用來加載Java的核心類庫

    1.1.2.2擴展類加載器

    由Java實現,派生于 ClassLoader 類。上層類加載器是引導類加載器(啟動類加載器),加載底層類庫

    1.1.2.3應用程序類加載器

    Java實現,派生于 ClassLoader 類。上層類加載器是擴展類加載器,加載自定義類。

    1.1.3 雙親委派機制

    加載類時,向上委派,交給最上層的加載器啟動類加載器加載核心類庫,加載不到就用擴展類加載器加載底層類庫,加載不到就用應用程序類加載器加載自定義類

    雙親委派機制的優點

    1. 安全,可避免用戶自己編寫的類動態替換 Java 的核心類(自定義的類名和Java核心類名相同)
    2. 避免全限定命名的類重復加載(使用了 findLoadClass()判斷當前類是否已加載)

    1.1.4沙箱安全機制

    作用是防止惡意代碼污染 Java 源代碼

    如果一個類在引導類加載器那里就加載到了,先找到先使用,所以就使用引導類加載器里面的類,后面的一概不能使用,這就保證了不被惡意代碼污染。

    1.1.5 類的主動使用和被動使用

    JVM 規定,每個類或者接口被首次主動使用時才對其進行初始化,有主動使用,自然就有被動使用。
    主動使用:

    1. 通過new關鍵字被導致類的初始化,這是大家經常使用的初始化一個類的方式,
      他肯定會導致類的加載并且初始化
    2. 訪問類的靜態變量,包括讀取和更新
    3. 訪問類的靜態方法
    4. 對某個類進行反射操作,會導致類的初始化
    5. 初始化子類會導致父類的的初始化
    6. 執行該類的 main 函數

    被動使用:其實除了上面的幾種主動使用其余就是被動使用了

    注意:主動使用和被動使用的區別在于類是否會被初始化.

    1. 引用該類的靜態常量,注意是常量,不會導致初始化,但是也有意外,這里的常量是指已經指定字面量的常量,對于那些需要一些計算才能得出結果的常量就會導致初始化,比如:
      public final static int number = 5 ; //不會導致類初始化,被動使用
      public final static int random = new Random().nextInt() ; //會導致類的初始化,主動使用
    2. 構造某個類的數組時不會導致該類的初始化,比如:
      Student[] students = new Student[10] ;

    1.2 運行時數據區

    JVM 的運行時數據區,不同虛擬機實現可能略微有所不同,但都會遵從 Java 虛擬機規范,Java 8 虛擬機規范規定,Java 虛擬機所管理的內存將會包括程序計數器、Java虛擬機棧、本地方法棧、Java堆、方法區。

    1.2.1 程序計數器(Program Counter Register)

    JVM 中的程序計數寄存器中的 Register 命名源于CPU 的寄存器,寄存器存儲指令相關的現場信息。這里,并非是廣義上所指的物理寄存器,或許將其翻譯為 PC 計數器(或指令計數器)會更加貼切(也稱為程序鉤子)。JVM 中的PC 寄存器是對物理 PC 寄存器的一種抽象模擬。

    1. 它是一塊很小的內存空間,幾乎可以忽略不計,但是它是運行速度最快的存儲區域。
    2. 在 JVM 規范中,每個線程都有它自己的程序計數器,是線程私有的,生命周期與線程生命周期保持一致。
    3. 任何時間一個線程都只有一個方法在執行,也就是所謂的當前方法,程序計數器會存儲當前線程正在執行的Java方法的JVM指令地址。如果是在執行native方法,則是未指定值(undefined)。
    4. 它是程序控制流的指示器,分支、循環、跳轉、異常處理,線程恢復等基礎功能都需要依賴這個計數器來完成。
    5. 字節碼解釋器工作時就是通過改變這個計數器的值來選取下一條需要執行的字節碼指令。
    6. 它是唯一一個在Java虛擬機規范中沒有規定任何 OutOfMemoryError 情況的區域.

    那么為什么使用程序計數器記錄當前線程的執行地址呢?我們都知道CPU需要不停的切換各個線程,這時候從其他線程切換到這個線程時,根據程序計數器就知道該從哪里開始執行了。JVM 的字節碼解釋器就需要通過改變程序計數器的值來明確下一條應該執行什么樣的字節碼指令,由于這個原因,必須為每個線程分配一個程序計數器,這樣各個線程就可以互不干擾。

    1.2.2 Java 虛擬機棧(Java Virtual Machine Stacks)

    首先我們需要學會區分棧和堆:

    棧是運行時的單位,而堆時存儲的單位。

    1. 棧:解決程序的運行問題,即程序如何執行,或者說如何處理數據。
    2. 堆:解決的是數據存儲的問題,即數據怎么放,放在哪兒。
    1.2.2.1 Java虛擬機棧概述

    每個線程在創建時都會創建一個虛擬機棧,其內部保存一個個棧幀,對應著一次方法的調用。Java 虛擬機棧是線程私有的。生命周期和線程一致。棧中的數據都以棧幀為單位存儲。棧幀是一個內存區塊,是一個數據集,維系著方法執行過程中的各種數據信息。

    作用:主要負責Java程序的運行,保存方法內的局部變量,還有部分結果,還參與方法的調用和返回。

    [外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-6hPYfqf3-1631455118244)(C:\Users\DELL\AppData\Roaming\Typora\typora-user-images\1631450877953.png)]

    棧是一種快速有效的分配存儲方式,訪問速度僅次于程序計數器。JVM 直接對 Java 棧的操作只有兩個:

    1. 調用方法,進棧。
    2. 執行結束后出棧。

    注意:對于棧來說不存在垃圾回收問題。

    1.2.2.2棧的運行原理
    1. JVM 直接對 Java 棧的操作只有兩個,就是對棧幀的壓棧和出棧,遵循”先進后出“后進先出的原則。
    2. 在一條活動的線程中,一個時間點上,只會有一個活動棧。即只有當前在執行的方法的棧幀(此時這個棧楨在棧頂)是有效地,這個棧幀被稱為當前棧(Current Frame),與當前棧幀對應的方法稱為當前方法(Current Method),定義這個方法的類稱為當前類(Current Class)。
    3. 執行引擎運行的所有字節碼指令只針對當前棧幀進行操作。
    4. 如果在該方法中調用了其他方法,對應的新的棧幀就會被創建出來,放在棧的頂端,成為新的當前棧幀。
    5. 不同線程中所包含的棧幀(方法)是不允許存在相互引用的,即不可能在一個棧中引用另一個線程的棧幀(方法)。
    6. 如果當前方法調用了其他方法,方法返回之際,當前棧幀會傳回此方法的執行結果給前一個棧幀,接著虛擬機會丟棄當前棧幀,使得前一個棧幀重新成為當前棧幀。Java 方法有兩種返回的方式,一種是正常的函數返回,使用 return 指令,另一種是拋出異常。不管哪種方式,都會導致棧幀被彈出.

    [外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-KE7YAljC-1631455118245)(C:\Users\DELL\AppData\Roaming\Typora\typora-user-images\1631451939150.png)]

    1.2.2.3 棧幀的內部

    每個棧幀中都有:局部變量表、操作數棧、動態鏈接、方法返回地址、一下附加信息。

    1.2.2.3.1局部變量表(Local Variables)

    局部變量表用于存放方法參數和方法內部定義的局部變量。

    對于基本數據類型的變量,則直接存儲它的值,對于引用類型的變量,則存的是指向對象的引用。

    1.2.2.3.2 操作數棧(Operand Stack)(或表達式棧)

    程序中的所有計算過程都是在借助于操作數棧來完成的。

    1.2.2.3.3 動態鏈接(Dynamic Linking) (或指向運行時常量池的方法引用)

    因為在方法執行的過程中有可能需要用到類中的常量或方法,所以必須要有一個引用指向運行時常量池。

    1.2.2.3.4 方法返回地址(Return Address)(或方法正常退出或者異常退出的定義)

    當一個方法執行完畢之后,要返回之前調用它的地方,因此在棧幀中必須保存一個方法返回地址。

    1.2.2.3.5 一些附加信息

    例如和調試相關的信息,這部分信息完全取決于不同的虛擬機實現。

    1.2.3 本地方法棧

    1. Java 虛擬機棧管理 java 方法的調用,而本地方法棧用于管理本地方法的調用。

    2. 本地方法棧也是線程私有的.

    3. 允許被實現成固定或者是可動態擴展的內存大小。

    內存溢出方面也是相同的。
    如果線程請求分配的棧容量超過本地方法棧允許的最大容量,會拋出StackOverflowError。
    如果本地方法可以動態擴展,并在擴展時無法申請到足夠的內存會拋出OutOfMemoryError。

    1. 本地方法是用 C 語言寫的.

    1.2.4 堆內存

    堆內存概述:

    1. 一個 JVM 實例只存在一個堆內存,堆也是 Java 內存管理的核心區域。
    2. Java 堆區在 JVM 啟動時的時候即被創建,其空間大小也就確定了,是 JVM 管理的最大一塊內存空間。
    3. 堆內存的大小是可以調節。一般情況可以將起始值和最大值設置為一致,這樣會減少垃圾回收之后堆內存重新分配大小的次數,提高效率。
    4. 《Java 虛擬機規范》規定,堆可以處于物理上不連續的內存空間中,但邏輯上它應該被視為連續的。
    5. 所有的線程共享 Java 堆,在這里還可以劃分線程私有的緩沖區。
    6. 《Java 虛擬機規范》中對 Java 堆的描述是:所有的對象實例都應當在運行時分配在堆上。
    7. 在方法結束后,堆中的對象不會馬上被移除,僅僅在垃圾收集的時候才會被移除。
    8. 堆是 GC(Garbage Collection,垃圾收集器)執行垃圾回收的重點區域。

    我們在之后在細講堆內存的區域劃分及垃圾回收機制

    1.2.5方法區

    方法區,是一個被線程共享的內存區域。其中主要存儲加載的類字節碼、class/method/field 等元數據、static final 常量、static 變量、編譯器編譯后的代碼等數據。另外,方法區包含了一個特殊的區域“運行時常量池”。
    Java 虛擬機規范中明確說明:”盡管所有的方法區在邏輯上是屬于堆的一部分,但對于HotSpotJVM 而言,方法區還有一個別名叫做 Non-Heap(非堆),目的就是要和堆分開。所以,方法區看做是一塊獨立于 Java 堆的內存空間。方法區在 JVM 啟動時被創建,并且它的實際的物理內存空間中和 Java 堆區一樣都可以是不連續的。
    方法區的大小:跟堆空間一樣,可以選擇固定大小或者可擴展。
    方法區的大小決定了系統可以保存多少個類,如果系統定義了太多的類,導致方法區溢出,虛擬機同樣會拋出內存溢出的錯誤 :java.lang.OutOfMemoryError:Metaspace。

    [外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-nuwBuYtn-1631455118248)(C:\Users\DELL\AppData\Roaming\Typora\typora-user-images\1631455014428.png)]

    結語

    這次就先寫這些,文中如果存在不對的地方,歡迎各位讀者批評指正。我會在今后更新本地方法接口執行引擎垃圾回收機制等相關內容,如果大家感興趣,可以關注博主,我們一起交流學習。

    本次的分享到這里就結束了,碼字不易,如果喜歡,賞個點贊+評論+收藏🤞🤞🤞,感謝您的支持

      轉藏 分享 獻花(0

      0條評論

      發表

      請遵守用戶 評論公約

      類似文章 更多

      主站蜘蛛池模板: 欧美国产日产一区二区| 宅男噜噜噜66网站高清| 免费人成网站视频在线观看 | 国产永久免费高清在线| 自偷自拍亚洲综合精品| 欧美日韩精品一区二区视频| 最新中文乱码字字幕在线| 国产精品免费久久久久影院| 国产精品美女久久久久久麻豆 | 久久精品99国产精品日本| 国产成人啪精品午夜网站| 精品久久久久久无码人妻热| 亚洲精品一区二区天堂| 久久精品国产一区二区三区| 国产日韩av二区三区| 免费一区二区无码东京热| 国产成人午夜精品福利| 国模吧无码一区二区三区| 伊人久久大香线蕉AV网禁呦| 成人久久免费网站| 国产XXXX色视频在线观看| 国产日韩综合av在线| 亚洲AV无码乱码在线观看性色扶 | 99久久精品国产一区二区蜜芽| 日本高清视频色欧WWW| av午夜福利一片免费看久久| 久久天天躁狠狠躁夜夜躁2020 | 国产永久免费高清在线| 再深点灬舒服灬太大了网站| 丰满少妇人妻HD高清大乳| 日韩精品区一区二区三vr| 中文字幕无码中文字幕有码A| 少妇粗大进出白浆嘿嘿视频| 一本一道VS无码中文字幕| 伊人久久大香线蕉成人| 日韩V欧美V中文在线| 精品国产成人A区在线观看| 免费无码又爽又刺激网站| 亚洲精品无码久久千人斩| 日本中文字幕有码在线视频| 97人妻人人做人碰人人爽|