国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

JVM——類加載和垃圾回收

這篇具有很好參考價值的文章主要介紹了JVM——類加載和垃圾回收。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

目錄

前言

JVM簡介

JVM內存區(qū)域劃分

JVM的類加載機制

1.加載

雙親委派模型

2.驗證

驗證選項

3.準備

4.解析

5.初始化

觸發(fā)類加載

JVM的垃圾回收策略 GC

一:找? ? ?誰是垃圾?

1.引用計數

2.可達性分析? (這個方案是Java采取的方案)。

二:釋放垃圾對象

三種典型的策略

JVM實現思路


前言

我們在學習JVM的時候,其實里面的內容是非常之多的,但是里面的大部分內容都是屬于八股,想要徹底搞明白,就需要看大量的關于JVM的源代碼,JVM的源代碼是C++寫的。想要深入研究的可以去看看《深入理解Java虛擬機》這本書。

這篇文章主要針對JVM中的常見的面試題來展開。

JVM簡介

JVM 是 Java Virtual Machine 的簡稱,意為 Java虛擬機。
虛擬機是指通過軟件模擬的具有完整硬件功能的、運行在一個完全隔離的環(huán)境中的完整計算機系統。
常見的虛擬機:JVM、VMwave、Virtual Box。
JVM 和其他兩個虛擬機的區(qū)別:

  1. VMwave與VirtualBox是通過軟件模擬物理CPU的指令集,物理系統中會有很多的寄存器;
  2. JVM則是通過軟件模擬Java字節(jié)碼的指令集,JVM中只是主要保留了PC寄存器,其他的寄存器都進行了裁剪。

JVM 是一臺被定制過的現實當中不存在的計算機。

JVM內存區(qū)域劃分

JVM其實就是一個Java進程,Java進程也就是JVM會從操作系統這里申請一大塊內存空間,給Java代碼來使用。

JVM從操作系統申請的這塊內存空間中,進行進一步的劃分,給出了每塊劃分后的空間的不同用途。

JVM——類加載和垃圾回收,JVM,jvm,后端,java

其中,最核心的就是棧、堆、元數據區(qū)(方法區(qū))。

  • 虛擬機棧是給Java代碼來使用的,主要存放一些局部變量,還有維護方法之間的調用關系。
  • 本地方法棧則是給JVM內部的本地方法來使用的。
  • 堆上存放的就是new出來的對象、成員變量。
  • 程序計數器中存放的就是一個內存地址,這個內存地址就是下一個要執(zhí)行字節(jié)碼所在的地址,作用就是記錄當前程序執(zhí)行到那個指令了。

需要注意的是,堆和元數據區(qū),在一個JVM 中只存在一份,也就是多個線程共享堆區(qū)和元數據區(qū)。

棧(本地方法棧和虛擬機棧)和程序計數器則是存在多份的,也就是每個線程都會有一份。

JVM的線程操作和操作系統的線程操作是一對一的關系。也就是說每次在Java代碼中創(chuàng)建的線程都會在操作系統中有一個線程與之對應。

這里的面試題主要就是判斷某個變量或者對象在JVM的那個區(qū)域?

例如下面代碼:

void func() {
    Test t1 = new Test();
}

上述代碼在一個方法里面我們實例化了一個Test對象。

JVM——類加載和垃圾回收,JVM,jvm,后端,java

?func方法是在元數據區(qū)以一些二進制的指令來存儲的。

我們可以看到t1變量是一個在方法里面定義的,所以他是一個局部變量,局部變量就存儲在棧上。

而new Test(); 這個對象的本體則是在堆上的。

其實像這里的關于JVM區(qū)域的面試題,我們只需要知道JVM的每個區(qū)域都是存儲什么東西的就好了。

  • 虛擬機棧是給Java代碼來使用的,主要存放一些局部變量,還有維護方法之間的調用關系。
  • 本地方法棧則是給JVM內部的本地方法來使用的。
  • 堆上存放的就是new出來的對象、成員變量。
  • 程序計數器中存放的就是一個內存地址,這個內存地址就是下一個要執(zhí)行字節(jié)碼所在的地址,作用就是記錄當前程序執(zhí)行到那個指令了。

JVM的類加載機制

對與一個類來說,他的生命周期是這樣的:

JVM——類加載和垃圾回收,JVM,jvm,后端,java

?前面的5步也是類加載的過程和固定的順序。我們主要研究前面的5步。

類加載具體就是把一個.class文件,也就是類編譯后的文件,加載到內存中,得到了類對象這樣的過程就稱之為類加載。

一個程序想要運行,就需要把指令和數據加載到內存中。類加載就是做的這個事情。

下面是類加載的5個步驟:

1.加載

這里的加載過程其實簡單,就是找到.class文件,然后讀取文件的內容。

但是在找.class文件的這個過程中,會有一個非常重要的機制:雙親委派模型

雙親委派模型

在JVM中,加載類需要用到一組特殊的模塊:類加載器。

在JVM中,內置了三個類加載器。

  • BootStrap ClassLoader? ? 負責加載Java標準庫中的類
  • Extension ClassLoader? ? ?負責加載一些非標準的但是是Sun/Oracle擴展庫的類
  • Application ClassLoader? ? 負責加載項目中自己寫的類、以及第三方庫中的類

當具體加載一個類的時候,他的過程是這樣的:

需要先給定一個類的全限定類名,"java.lang.String"? 這個類名是一個字符串的形式。

如果一個類加載器收到了類加載的請求,它首先不會自己去嘗試加載這個類,而是把這個請求委派給父類加載器去完成,每一個層次的類加載器都是如此,因此所有的加載請求最終都應該傳送到最頂層BootStrap ClassLoader類加載器中,只有當父加載器反饋自己無法完成這個加載請求(它的搜索范圍中沒有找到所需的類)時,子加載器才會嘗試自己去完成加載。

具體可以參考下圖:

JVM——類加載和垃圾回收,JVM,jvm,后端,java

2.驗證

由于.class文件有著明確的數據格式(二進制的),這一階段的主要目的就是確保Class文件中的字節(jié)流中包含的信息符合《Java虛擬機規(guī)范》的全部約束要求。

驗證選項

文件格式驗證

字節(jié)碼驗證

符號引用驗證……

3.準備

準備階段是正式為類中定義的變量(即靜態(tài)變量,被static修飾的變量)分配內存并設置類變量初始值的階段。

比如下面這樣的代碼:

public static int value = 123;

此時在準備階段value的值并不是123,而是0。
?

4.解析

解析階段是Java虛擬機將常量池內的符號引用替換為直接引用的過程,也就是初始化常量的過程。

  • 符號引用:就是字符串常量在.class文件已經存在,但是他們只知道彼此之間的相對位置,并不知道自己在內存中的具體位置。
  • 直接引用:真正的加載到內存中,就會把字符串常量填充到內存中的特定地址上去。此時字符串引用的就是直接引用,(也就是Java中普通的引用)。

5.初始化

在初始化階段,JVM才真正的執(zhí)行類中編寫的Java代碼,將主導權交給應用程序,初始化階段就是執(zhí)行類的構造方法的過程。(類要是有父類,就需要先初始化父類,在初始化子類)。

觸發(fā)類加載

注意:類加載這個動作不是說JVM一啟動就會進行加載,因為JVM整體是一個懶加載的策略,也就是非必要,不加載。

以下三種請況就會加載:

  1. 創(chuàng)建了這個類的實例
  2. 使用了這個類的靜態(tài)方法/靜態(tài)屬性
  3. 使用子類,會觸發(fā)父類的加載

JVM的垃圾回收策略 GC

Java中的垃圾回收是為了幫助我們自動釋放內存的一種機制。

面試題:為什么需要垃圾回收機制

因為在程序運行過程中,會向操作系統申請大量的內存空間,但是這些空間也有可能會消耗盡,因為不斷地分配內存空間而不進行回收,就好像不停地生產生活垃圾而從來不打掃一樣。

上面我們談到了關于JVM的幾個區(qū)域,那么垃圾回收釋放的是那個區(qū)域的空間呢?

需要注意的是,棧和程序計數器是每個線程都會有一份的。他們會隨著線程的銷毀而一起銷毀的。

而元數據區(qū)里面的存儲的類對象,很少會進行銷毀。

所以我們釋放的就是堆中的空間。上面我們談到堆中主要就是存放new 出來的對象的。

GC也就是以對象為單位進行釋放的。(釋放對象)

GC中主要分為兩個階段:

一:找? ? ?誰是垃圾?

Java通過引用來判斷是否是垃圾對象,如果沒有引用指向,就判定這個對象是垃圾。

1.引用計數

給對象安排一個額外的空間,保存了一個整數,表示該對象有幾個引用指向它。Java實際上并沒有采取這樣的方案,(Python、PHP采用了這個方案)。

Test t1 = new Test();

JVM——類加載和垃圾回收,JVM,jvm,后端,java

?此時是有一個引用指向的,所以引用計數器為1。

如果代碼變成這樣:

Test t1 = new Test();
Test t2 = t1;

JVM——類加載和垃圾回收,JVM,jvm,后端,java

?也就是說隨著引用的增加,計數器就會增加,引用的銷毀,計數器就會減少。

當計數器為0時,就會認為該對象沒有引用指向了,就是垃圾了。

但是缺點也是很明顯:

  1. 浪費內存空間
  2. 存在循壞引用的情況

2.可達性分析? (這個方案是Java采取的方案)。

把對象之間的引用關系理解成為了一個樹形結構,從一些特殊的起點出發(fā),進行遍歷,只要能訪問到,是可達的,不是垃圾,再把不可達的當做垃圾即可。

JVM——類加載和垃圾回收,JVM,jvm,后端,java

?此時通過root這個引用是可以訪問到整個樹的任意節(jié)點的。

可達性分析的關鍵要點在于要進行上述的遍歷,需要有起點的。

起點可以是:

  1. 棧上的局部變量(每個棧的每個局部變量都是起點)
  2. 常量池中引用的對象
  3. 方法區(qū)中靜態(tài)成員引用的對象

可達性分析,總體就是從所有的起點出發(fā),看看該對象里面又通過哪些引用能訪問到那些對象,順藤摸瓜的把所有可以訪問的對象都訪問一遍,遍歷的同時把對象標記為“可達”。

可達性分析,克服了引用計數的兩個缺點

但是也是有自己的問題:

  • 消耗更多的時間 因此即使某個對象成了垃圾,也不能第一時間發(fā)現,因為在掃描的過程中,也是需要時間的。
  • 在進行可達性分析的時候,要順藤摸瓜,一旦這個過程中,當前代碼中的對象的引用關系發(fā)生了變化,就可以出現bug。

因此為了更好的完成這個順藤摸瓜的過程,就需要讓其他的業(yè)務線程都暫停工作?。。。⊿TW)

(STW)? ?stop the world !

但是Java畢竟發(fā)展了這么多年,拉進回收這里也是在不斷的進行優(yōu)化,STW這個問題也可以比較好的對付了。

二:釋放垃圾對象

三種典型的策略

1:標記清除

?如果現在向內存申請了一塊下面這樣的空間,然后我標出來的就是垃圾對象,需要清除的。

JVM——類加載和垃圾回收,JVM,jvm,后端,java

?這種策略就是直接把垃圾對象的內存就釋放了。

但是這種簡單粗暴的方式會產生內存碎片。

內存碎片:申請空間都是連續(xù)的整塊空間,現在上述圖中的空閑空間都是散落在獨立的空間里面的。現在空閑總空間可能超過1G,但是我想申請500M,卻是申請不了。

2:復制算法

這種方法是把空間分為兩部分。一次只使用一半。

復制算法就是把不是垃圾的對象拷貝到一邊去,然后在統一釋放整個區(qū)域。

JVM——類加載和垃圾回收,JVM,jvm,后端,java

?此時我要釋放的是2和4,我就需要把剩下1和3復制到另一邊去。然后再把這邊全部釋放。

JVM——類加載和垃圾回收,JVM,jvm,后端,java

?復制算法解決了內存碎片的問題,但是也有缺點:

  • 內存利用率比較低
  • 如果大部分對象都是保留的,垃圾很少,此時的復制成本就比較高

3:標記整理

類似于順序表刪除中間元素,有一個搬運的過程

JVM——類加載和垃圾回收,JVM,jvm,后端,java?解決了內存碎片問題但是搬運的整體開銷也是比較大的。

JVM實現思路

實際上,JVM的實現方式是結合了上述幾種思想之后的方法。

分代回收思想

具體細節(jié):

  • 給對象設置年齡這樣的概念,用來描述這個對象存在多久了。如果一個對象剛誕生,那么就是0歲。
  • 每次進過一次掃描(可達性分析)如果沒有被標記為垃圾對象,這是對象年齡就增加一歲。
  • 通過年齡來區(qū)分這個對象的活動時間。

經驗規(guī)律:年齡越大的對象,也將會持續(xù)存在更長的時間。

針對不同的年齡來采取不同的回收策略

JVM——類加載和垃圾回收,JVM,jvm,后端,java

JVM針對這幾個區(qū)域來執(zhí)行不同的策略。

1:新創(chuàng)建的對象,放在伊甸區(qū)

垃圾回收掃描到伊甸區(qū)之后,大多數的對象將會在第一輪掃描下被GC給淘汰掉。

2:如果伊甸區(qū)的對象,熬過第一輪GC,就會通過復制算法,拷貝到生存區(qū)。

生存區(qū)分為兩半(大小相等),一次只使用其中的一半。

如果GC在掃描生存區(qū)的時候,發(fā)現垃圾對象也就淘汰,不是垃圾的,就通過復制算法拷貝到生存區(qū)的另一邊。

3:當對象在生存區(qū)熬過了若干次GC的時候,年齡也變大了。此時就會通過復制算法拷貝到老年代。

4:進入老年代之后,由于年齡都比較大了,被標記為垃圾對象的概念也很小,所以針對老年代的GC掃描也會降低頻率。

特殊情況:如果對象非常大,直接進入老年代(大對象進行復制算法,成本非常高,而且大對象也不會很多)。文章來源地址http://www.zghlxwxcb.cn/news/detail-562850.html

到了這里,關于JVM——類加載和垃圾回收的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。如若轉載,請注明出處: 如若內容造成侵權/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經查實,立即刪除!

領支付寶紅包贊助服務器費用

相關文章

  • 了解 JVM - 認識垃圾回收機制與類加載過程

    了解 JVM - 認識垃圾回收機制與類加載過程

    本篇通過介紹JVM是什么,認識JVM的內存區(qū)域的劃分,了解類加載過程,JVM中垃圾回收機制,從中了解到垃圾回收機制中如何找到存活對象的方式,引用計數與可達性分析的方式,再釋放垃圾對象時使用的方式,標準清除,復制算法,標準整理,分代回收等等,如有錯誤,請在

    2024年02月16日
    瀏覽(34)
  • JVM解密: 解構類加載與GC垃圾回收機制

    JVM解密: 解構類加載與GC垃圾回收機制

    JVM 其實是一個 Java 進程,該進程會從操作系統中申請一大塊內存區(qū)域,提供給 Java 代碼使用,申請的內存區(qū)域會進一步做出劃分,給出不同的用途。 其中最核心的是棧,堆,方法區(qū)這幾個區(qū)域: 堆,用來放置 new 出來的對象,類成員變量。 棧,維護方法之間的調用關系,放

    2024年02月10日
    瀏覽(24)
  • JVM基礎知識(內存區(qū)域劃分,類加載,GC垃圾回收)

    JVM基礎知識(內存區(qū)域劃分,類加載,GC垃圾回收)

    目錄 內存區(qū)域劃分 JVM中的棧 JVM中的堆 程序計數器 方法區(qū)(元數據區(qū)) 給一段代碼,某個變量在哪個區(qū)域上? 類加載 類加載時機 雙親委派模型 GC 垃圾回收機制 GC 實際工作過程 1.找到垃圾/判定垃圾 1.可達性分析(Java中的做法) 2.引用計數 2.清理垃圾 1.標記清除 2.復制算法 3.標記整

    2024年02月07日
    瀏覽(27)
  • 【Java JVM】垃圾回收

    【Java JVM】垃圾回收

    當前大部分的垃圾收集器都遵循著 “分代收集” (Generational Collection) 的理論進行設計的, 建立在 2 個分代假設之上 弱分代假說 (Weak Generational Hypothesis): 絕大多數對象都是朝生夕滅的 強分代假說 (Strong Generational Hypothesis): 熬過越多次垃圾收集過程的對象就越難以消亡 根據這

    2024年03月14日
    瀏覽(19)
  • 3.Java面試題—JVM基礎、內存管理、垃圾回收、JVM 調優(yōu)

    3.Java面試題—JVM基礎、內存管理、垃圾回收、JVM 調優(yōu)

    一篇文章掌握整個JVM,JVM超詳細解析?。?! JVM (Java虛擬機) 是運行 Java 字節(jié)碼 的 虛擬機 。 JVM 針對 不同系統 有 特定實現 ( Windows 、 Linux 等),目的是 同樣的代碼 在 不同平臺 能運行出 相同的結果 。 Java 語言 要經過 編譯 和 解釋 兩個步驟: 編譯 :通過 編譯器 將 代碼 一

    2024年02月15日
    瀏覽(22)
  • 【Java】圖解 JVM 垃圾回收(一):GC 判斷策略、引用類型、垃圾回收算法

    【Java】圖解 JVM 垃圾回收(一):GC 判斷策略、引用類型、垃圾回收算法

    垃圾 是指運行程序中 沒有任何引用指向的對象 ,需要被回收。 內存溢出 :經過垃圾回收之后,內存仍舊無法存儲新創(chuàng)建的對象,內存不夠溢出。 內存泄漏 :又叫 “ 存儲泄漏 ”,對象不會再被程序使用了,但是 GC 又不能回收它們。例如:IO 流不適用了但是沒有被 Close、

    2024年02月19日
    瀏覽(25)
  • Java虛擬機(JVM)、垃圾回收器

    Java虛擬機(JVM)、垃圾回收器

    JRE(Java Runtime Environment,運行環(huán)境) 所有的程序都要在JRE下才能夠運行。包括JVM和Java核心類庫和支持文件。 JDK(Java Development Kit,開發(fā)工具包) 用來編譯、調試Java程序的開發(fā)工具包。包括Java工具(javac/java/jdb等)和Java基礎的類庫(java API )。 JVM(Java Virtual Machine,虛擬機) JRE的一部分,

    2024年02月12日
    瀏覽(20)
  • java八股文面試[JVM]——垃圾回收

    java八股文面試[JVM]——垃圾回收

    參考:JVM學習筆記(一)_卷心菜不卷Iris的博客-CSDN博客 GC垃圾回收 面試題: JVM內存模型 以及分區(qū),需要詳細到每個區(qū)放什么 堆里面的分區(qū):Eden,survival from to,老年代,各自的特點。 GC的三種收集方法:標記清除、標記整理、復制算法的原理與特點,分別用在什么地方 針

    2024年02月11日
    瀏覽(44)
  • 【Java虛擬機】JVM垃圾回收機制和常見回收算法原理

    【Java虛擬機】JVM垃圾回收機制和常見回收算法原理

    1.垃圾回收機制 (1)什么是垃圾回收機制(Garbage Collection, 簡稱GC) 指自動管理動態(tài)分配的內存空間的機制,自動回收不再使用的內存,以避免內存泄漏和內存溢出的問題 最早是在1960年代提出的,程序員需要手動管理內存的分配和釋放 這往往會導致內存泄漏和內存溢出等問

    2024年02月02日
    瀏覽(37)
  • java八股文面試[JVM]——垃圾回收器

    java八股文面試[JVM]——垃圾回收器

    jvm結構總結 ? 常見的垃圾回收器有哪些? ? ? CMS(Concurrent Mark Sweep) 整堆收集器 : G1 由于整個過程中 耗時最長 的 并發(fā)標記 和 并發(fā)清除 過程中,收集器線程都可以與用戶線程一起工作,所以 總體上來說 ,CMS收集器的內存回收過程是與用戶線程一起并發(fā)地執(zhí)行。老年代收

    2024年02月11日
    瀏覽(28)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領取紅包,優(yōu)惠每天領

二維碼1

領取紅包

二維碼2

領紅包