淺析 JVM 知識點(一)

      網友投稿 867 2025-03-31

      一.類加載


      1.基本類型和 String 類型被 static final 修飾時不會觸發類的加載,當子類訪問父類成員觸發類加載時,父類為主動加載,子類為被動加載,被動加載不會執行代碼塊.

      什么是雙親委派機制

      雙親委派機制:首先把這個任務委托給他的上級類加載器,遞歸這個操作,如果上級的類加載器沒有加載,自己才會去加載這個類。

      BootstrapClassLoader(啟動類加載器)由 C++ 編寫,加載 Java 核心庫 java.* ,同時構造 ExtClassLoader 和 AppClassLoader。由于引導類加載器涉及到虛擬機本地實現細節,開發者無法直接獲取到啟動類加載器的引用,所以不允許直接通過引用進行操作.

      ExtClassLoader (標準擴展類加載器)由 Java編寫,加載擴展庫,如classpath 中的 jre ,javax.* 或者 java.ext.dir 指定位置中的類,開發者可以直接使用標準擴展類加載器。

      AppClassLoader(系統類加載器)由 Java編寫,加載程序所在的目錄,如user.dir 所在的位置的 class

      CustomClassLoader(用戶自定義類加載器)由 Java 編寫,用戶自定義的類加載器,可加載指定路徑的 class 文件

      類加載

      類加載:類的加載指的是將類的 .class 文件中的二進制數據讀入到內存中,將其放在運行時數據區的方法區內,然后在堆區創建一個 java.lang.Class 對象,用來封裝類在方法區內的數據結構

      類加載過程:類從被加載到虛擬機內存中開始,到卸載出內存為止,它的整個生命周期包括:加載、驗證、準備、解析、初始化、使用和卸載七個階段

      其中類加載的過程包括了加載、驗證、準備、解析、初始化五個階段。在這五個階段中,加載、驗證、準備和初始化這四個階段發生的順序是確定的,而解析階段則不一定,它在某些情況下可以在初始化階段之后開始。

      另外注意這里的幾個階段是按順序開始,而不是按順序進行或完成,因為這些階段通常都是互相交叉地混合進行的,通常在一個階段執行的過程中調用或激活另一個階段。

      1、加載

      ”加載“是”類加機制”的第一個過程,在加載階段,虛擬機主要完成三件事:

      通過一個類的全限定名來獲取其定義的二進制字節流

      將這個字節流所代表的的靜態存儲結構轉化為方法區的運行時數據結構

      在堆中生成一個代表這個類的Class對象,作為方法區中這些數據的訪問入口。

      相對于類加載的其他階段而言,加載階段是可控性最強的階段,因為程序員可以使用系統的類加載器加載,還可以使用自己的類加載器加載。我們在最后一部分會詳細介紹這個類加載器。在這里我們只需要知道類加載器的作用就是上面虛擬機需要完成的三件事,僅此而已就好了。

      2、驗證

      驗證的主要作用就是確保被加載的類的正確性。也是連接階段的第一步。說白了也就是我們加載好的 .class 文件不能對我們的虛擬機有危害,所以先檢測驗證一下。他主要是完成四個階段的驗證:

      文件格式的驗證:驗證 .class 文件字節流是否符合 class 文件的格式的規范,并且能夠被當前版本的虛擬機處理。這里面主要對魔數、主版本號、常量池等等的校驗(魔數、主版本號都是 .class 文件里面包含的數據信息、在這里可以不用理解)。

      元數據驗證:主要是對字節碼描述的信息進行語義分析,以保證其描述的信息符合java語言規范的要求,比如說驗證這個類是不是有父類,類中的字段方法是不是和父類沖突等等。

      字節碼驗證:這是整個驗證過程最復雜的階段,主要是通過數據流和控制流分析,確定程序語義是合法的、符合邏輯的。在元數據驗證階段對數據類型做出驗證后,這個階段主要對類的方法做出分析,保證類的方法在運行時不會做出危害虛擬機安全的事。

      符號引用驗證:它是驗證的最后一個階段,發生在虛擬機將符號引用轉化為直接引用的時候。主要是對類自身以外的信息進行校驗。目的是確保解析動作能夠完成。

      對整個類加載機制而言,驗證階段是一個很重要但是非必需的階段,如果我們的代碼能夠確保沒有問題,那么我們就沒有必要去驗證,畢竟驗證需要花費一定的的時間。當然我們可以使用 -Xverfity:none 來關閉大部分的驗證。

      3、準備

      準備階段主要為類變量分配內存并設置初始值。這些內存都在方法區分配。在這個階段我們只需要注意兩點就好了,也就是類變量和初始值兩個關鍵詞:

      類變量(static)會分配內存,但是實例變量不會,實例變量主要隨著對象的實例化一塊分配到java堆中,

      這里的初始值指的是數據類型默認值,而不是代碼中被顯示賦予的值。比如public static int value = 1 ; 在這里準備階段過后的 value 值為 0,而不是 1。賦值為 1 的動作在初始化階段。

      注意,在上面 value 是被 static 所修飾的準備階段之后是 0,但是如果同時被 final 和 static 修飾準備階段之后就是 1 了。我們可以理解為 static final在編譯期就將結果放入調用它的類的常量池中了。

      4、解析

      解析階段主要是虛擬機將常量池中的符號引用轉化為直接引用的過程。什么是符號應用和直接引用呢?

      符號引用:以一組符號來描述所引用的目標,可以是任何形式的字面量,只要是能無歧義的定位到目標就好,就好比在班級中,老師可以用張三來代表你,也可以用你的學號來代表你,但無論任何方式這些都只是一個代號(符號),這個代號指向你(符號引用)

      直接引用:直接引用是可以指向目標的指針、相對偏移量或者是一個能直接或間接定位到目標的句柄。和虛擬機實現的內存有關,不同的虛擬機直接引用一般不同。解析動作主要針對類或接口、字段、類方法、接口方法、方法類型、方法句柄和調用點限定符7類符號引用進行。

      5、初始化

      這是類加載機制的最后一步,在這個階段,java程序代碼才開始真正執行。我們知道,在準備階段已經為類變量賦過一次值。在初始化階端,程序員可以根據自己的需求來賦值了。一句話描述這個階段就是執行類構造器< clinit >() 方法的過程。

      在初始化階段,主要為類的靜態變量賦予正確的初始值,JVM 負責對類進行初始化,主要對類變量進行初始化。在 Java 中對類變量進行初始值設定有兩種方式:

      聲明類變量是指定初始值

      使用靜態代碼塊為類變量指定初始值

      JVM初始化步驟

      假如這個類還沒有被加載和連接,則程序先加載并連接該類

      假如該類的直接父類還沒有被初始化,則先初始化其直接父類

      假如類中有初始化語句,則系統依次執行這些初始化語句

      Class初始時機:

      創建類的實例(四種方式) new/反射instance/序列化/clone

      訪問類中的某個靜態變量,或者對靜態變量賦值

      主動調用類的靜態方法

      class.forName(“全限定類名”)

      完成子類的初始化,也會對本類的初始化(接口例外)

      該類是程序引導入口(main入口或者test入口)

      雙親委派機制的作用

      防止重復加載同一個.class。通過委托去向上面問一問,加載過了,就不用再加載一遍。保證數據安全。

      保證核心.class不能被篡改。通過委托方式,不會去篡改核心.class,即使篡改也不會去加載,即使加載也不會是同一個 .class 對象了。不同的加載器加載同一個 .class 也不是同一個 Class 對象。這樣保證了 Class 執行安全。

      自定義類加載器

      在這一部分第一小節中,我們提到了 Java 系統為我們提供的三種類加載器,還給出了他們的層次關系圖,最下面就是自定義類加載器,那么我們如何自己定義類加載器呢?這主要有兩種方式

      遵守雙親委派模型:繼承 ClassLoader,重寫 findClass() 方法。

      破壞雙親委派模型:繼承 ClassLoader ,重寫 loadClass() 方法。 通常我們推薦采用第一種方法自定義類加載器,最大程度上的遵守雙親委派模型。

      我們看一下實現步驟:

      創建一個類繼承 ClassLoader 抽象類

      重寫 findClass() 方法

      在 findClass() 方法中調用 defineClass()

      二.JVM 內存模型

      JVM 可以分為內存模型、類加載子系統、字節碼執行引擎三部分,其中主要分析內存模型。

      內存模型由虛擬機棧,堆,程序計數器,本地方法棧組成,其中方法區在 jdk8 中由元數據區替代,并且堆中的永久代也移至元數據區,此塊空間使用的是 os 中的直接內存.

      虛擬機棧

      淺析 JVM 知識點(一)

      虛擬機棧由局部變量表,操作數棧,動態鏈接,方法出口組成,每執行一個方法都會對應的在棧中創建一個棧幀,方法的執行和結束對應著虛擬機棧的入棧出棧.生命周期與線程相同,線程私有。堆和元數據區為線程共享。棧幀中局部變量表 數量,如果是類方法(static)是從0開始的,如果是從1開始的話,0的被this當前對象使用

      堆空間由年輕代,老年代組成其中年輕代占 1/3 ,老年代占 2/3 ,永久代在 JDK8 移至元數據區.其中年輕代分為 eden 和 from、to,占比為 8/10 , 2/10.

      在創建對象時會在 eden 中初始一次,當 Eden 區滿的時候,執行 Minor GC,將消亡的對象清理掉,并將剩余的對象復制到一個存活區 Survivor0(此時,Survivor1是空白的,兩個 Survivor 總有一個是空白的);

      下次 Eden 區滿了,再執行一次 Minor GC,將消亡的對象清理掉,將存活的對象復制到 Survivor1中,然后清空 Eden 區,將 Survivor0 中消亡的對象清理掉,將其中可以晉級的對象晉級到 Old 區,將存活的對象也復制到 Survivor1 區,然后清空 Survivor0 區;

      當兩個存活區切換了幾次(HotSpot虛擬機默認15次,用 -XX:MaxTenuringThreshold 控制,大于該值進入老年代,但這只是個最大值,并不代表一定是這個值)之后,仍然存活的對象(其實只有一小部分,比如,我們自己定義的對象),將被復制到老年代.

      當老年代存滿后會執行 FULLGC ,此時停止所有線程等待清除.

      本地方法棧

      本地方法棧:用于調用本地方法

      程序計數器

      程序計數器:用于存儲 JVM 指令,因為多線程環境下,CPU 頻繁的切換,需要記錄 JVM 指令的位置

      元數據區

      元數據區:使用操作系統內存,用于存儲字符串常量池,常量,靜態方法,類字節碼信息,因為 JDK 廠商的不同,在 JDK8 時將永久代并入元數據區.

      三.四大引用

      強引用:如 Object o=new Object() 此類引用即使內存溢出也不會被gc回收掉

      弱引用:如 WeakRefence sr=new WekRefence(Object o) 此類引用觸發GC時會回收此對象

      軟引用:如 SoftRefence wr=new SoftRrfence(Object o) 此類引用內存溢出時直接被回收

      虛引用:不常用,用于gc時通知,隨時可以被回收

      四.逃逸分析

      JVM 開啟逃逸后會分析創建的對象是否分配在堆中.開啟后有以下好處:

      鎖消除:如果該對象只在當前線程使用那么它可以是不同步的

      標量替換:基本類型和對象的引用可以理解為標量而對象可理解為聚合量,標量不可再分解,而聚合量可以再分解為標量,當這個對象的訪問方式不需要是一塊連續的內存結構時,它可以存儲在 CPU 寄存器中

      棧上分配:如果該對象的引用永遠不會逃逸,那么它可以分配在棧上

      volatile關鍵字作用

      防止jvm指令重排序(jvm在編譯時會進行指令重排序)

      保證可見性(一個線程的修改對另個線程是可見的)

      不保證原子性(可由 syhcnhronized 保證,即保證原子性也可以保證可見性或使用 JUC 包中,如原子類, AtomicInteger)

      Java JVM

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:安卓excel表單(excel android app)
      下一篇:刪除怎么恢復(微信消息刪除怎么恢復)
      相關文章
      亚洲精品无码一区二区| 亚洲最大中文字幕无码网站| 国产成人综合亚洲一区| 亚洲另类自拍丝袜第五页| 亚洲高清中文字幕免费| 亚洲卡一卡2卡三卡4麻豆| 亚洲熟妇av一区二区三区下载| 亚洲综合视频在线观看| 亚洲成人中文字幕| 亚洲成人中文字幕| 亚洲精品在线电影| 亚洲伊人色一综合网| 亚洲精品伊人久久久久| 亚洲看片无码在线视频| 久久亚洲国产成人影院| 亚洲欧美综合精品成人导航| 亚洲欧洲无码AV不卡在线| 亚洲AV无码AV日韩AV网站| 精品韩国亚洲av无码不卡区| 亚洲AV永久无码精品一区二区国产| 亚洲Aⅴ无码一区二区二三区软件 亚洲AⅤ视频一区二区三区 | 亚洲区小说区图片区QVOD| 亚洲一区二区三区无码中文字幕| 国产精品亚洲二区在线观看| 亚洲欧洲日产国码无码网站 | 亚洲人成色99999在线观看| 亚洲成a人片在线观看天堂无码 | 亚洲第一区视频在线观看| 亚洲免费在线视频播放| 亚洲日本国产综合高清| 亚洲乱妇熟女爽到高潮的片 | 亚洲美女激情视频| 久久夜色精品国产噜噜亚洲a| 亚洲色大成网站www久久九| 含羞草国产亚洲精品岁国产精品| 亚洲av无码国产精品色在线看不卡 | 亚洲毛片基地4455ww| 亚洲AV无码AV日韩AV网站| 亚洲成a人一区二区三区| 久久久无码精品亚洲日韩软件 | 亚洲日韩看片无码电影|