中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁 > news >正文

網(wǎng)站域名com和cn百度識(shí)圖網(wǎng)頁版

網(wǎng)站域名com和cn,百度識(shí)圖網(wǎng)頁版,分銷商城開發(fā)公司,做網(wǎng)站需要學(xué)什么🐮🐮🐮 辛苦牛,掌握主流技術(shù)棧,包括前端后端,已經(jīng)7年時(shí)間,曾在稅務(wù)機(jī)關(guān)從事開發(fā)工作,目前在國(guó)企任職。希望通過自己的不斷分享,可以幫助各位想或者已經(jīng)走在這條路上的朋友…

🐮🐮🐮
辛苦牛,掌握主流技術(shù)棧,包括前端后端,已經(jīng)7年時(shí)間,曾在稅務(wù)機(jī)關(guān)從事開發(fā)工作,目前在國(guó)企任職。希望通過自己的不斷分享,可以幫助各位想或者已經(jīng)走在這條路上的朋友一定的幫助

目錄

  • 前言
    • 📟 Q1:運(yùn)行時(shí)數(shù)據(jù)區(qū)是什么?
    • 📟 Q2:程序計(jì)數(shù)器是什么?
    • 📟 Q3:Java 虛擬機(jī)棧的作用?
    • 📟 Q4:本地方法棧的作用?
    • 📟 Q5:堆的作用是什么?
    • 📟 Q6:方法區(qū)的作用是什么?
    • 📟 Q7:運(yùn)行時(shí)常量池的作用是什么?
    • 📟 Q8:直接內(nèi)存是什么?
    • 📟 Q9:內(nèi)存溢出和內(nèi)存泄漏的區(qū)別?
    • 📟 Q10:堆溢出的原因?
    • 📟 Q11:棧溢出的原因?
    • 📟 Q12:運(yùn)行時(shí)常量池溢出的原因?
    • 📟 Q13:方法區(qū)溢出的原因?
    • 📟 Q14:創(chuàng)建對(duì)象的過程是什么? 字節(jié)碼?度
    • 📟 Q15:對(duì)象分配內(nèi)存的方式有哪些?
    • 📟 Q16:對(duì)象分配內(nèi)存是否線程安全?
    • 📟 Q17:對(duì)象的內(nèi)存布局了解嗎?
    • 📟 Q18:對(duì)象的訪問方式有哪些?
    • 📟 Q19:如何判斷對(duì)象是否是垃圾?
    • 📟 Q20:Java 的引用有哪些類型?
    • 📟 Q21:有哪些 GC 算法?
    • 📟 Q22:你知道哪些垃圾收集器?
    • 📟 Q23:ZGC 了解嗎?
    • 📟 Q24:你知道哪些內(nèi)存分配與回收策略?
    • 📟 Q25:你知道哪些故障處理工具?
    • 📟 Q26:Java 程序是怎樣運(yùn)行的?
    • 📟 Q27:類加載是什么?
    • 📟 Q28:類初始化的情況有哪些?
    • 📟 Q29:類加載的過程是什么? 加載
    • 📟 Q30:有哪些類加載器?
    • 📟 Q31:雙親委派模型是什么?
    • 📟 Q32:如何判斷兩個(gè)類是否相等?
  • 寫在最后

前言

??金九銀十馬上就要來啦,各位小伙伴們有計(jì)劃跳槽的要開始準(zhǔn)備了,博主接下來一段時(shí)間會(huì)給大家持續(xù)更新面試題目,大家持續(xù)關(guān)注一下,感謝🙏🙏🙏
今天是JVM的相關(guān)面試題,歡迎指正
之前的面試文章鏈接也給到大家
金九銀十面試題之Mysql
金九銀十面試題之設(shè)計(jì)模式
金九銀十面試題之?dāng)?shù)據(jù)結(jié)構(gòu)和算法
金九銀十面試題之Mybatis
金九銀十面試題之《Spring Data JPA、Spring MVC、AOP》
金九銀十面試題之《Spring IOC》
金九銀十面試題之JUC
金九銀十面試題之《并發(fā)》

📟 Q1:運(yùn)行時(shí)數(shù)據(jù)區(qū)是什么?

虛擬機(jī)在執(zhí)行 Java 程序的過程中會(huì)把它所管理的內(nèi)存劃分為若干不同的數(shù)據(jù)區(qū),這些區(qū)域有各自的用途、
創(chuàng)建和銷毀時(shí)間。
線程私有:程序計(jì)數(shù)器、Java 虛擬機(jī)棧、本地方法棧。
線程共享:Java 堆、方法區(qū)。

📟 Q2:程序計(jì)數(shù)器是什么?

程序計(jì)數(shù)器是一塊較小的內(nèi)存空間,可以看作當(dāng)前線程所執(zhí)行字節(jié)碼的行號(hào)指示器。字節(jié)碼解釋器工作 時(shí)通過改變計(jì)數(shù)器的值選取下一條執(zhí)行指令。分支、循環(huán)、跳轉(zhuǎn)、線程恢復(fù)等功能都需要依賴計(jì)數(shù)器完 成。是唯一在虛擬機(jī)規(guī)范中沒有規(guī)定內(nèi)存溢出情況的區(qū)域。
如果線程正在執(zhí)行 Java 方法,計(jì)數(shù)器記錄正在執(zhí)行的虛擬機(jī)字節(jié)碼指令地址。如果是本地方法,計(jì)數(shù)器值為 Undefined。

📟 Q3:Java 虛擬機(jī)棧的作用?

Java 虛擬機(jī)棧來描述 Java 方法的內(nèi)存模型。每當(dāng)有新線程創(chuàng)建時(shí)就會(huì)分配一個(gè)??臻g,線程結(jié)束后棧 空間被回收,棧與線程擁有相同的生命周期。棧中元素用于支持虛擬機(jī)進(jìn)行方法調(diào)用,每個(gè)方法在執(zhí)行 時(shí)都會(huì)創(chuàng)建一個(gè)棧幀存儲(chǔ)方法的局部變量表、操作棧、動(dòng)態(tài)鏈接和方法出口等信息。每個(gè)方法從調(diào)用到 執(zhí)行完成,就是棧幀從入棧到出棧的過程。

有兩類異常:

  1. 線程請(qǐng)求的棧深度大于虛擬機(jī)允許的深度拋出 StackOverflowError。
  2. 如果 JVM 棧容 量可以動(dòng)態(tài)擴(kuò)展,棧擴(kuò)展無法申請(qǐng)足夠內(nèi)存拋出 OutOfMemoryError(HotSpot 不可動(dòng)態(tài)擴(kuò)展,不存在 此問題)。

📟 Q4:本地方法棧的作用?

本地方法棧與虛擬機(jī)棧作用相似,不同的是虛擬機(jī)棧為虛擬機(jī)執(zhí)行 Java 方法服務(wù),本地方法棧為虛本地
方法服務(wù)。調(diào)用本地方法時(shí)虛擬機(jī)棧保持不變,動(dòng)態(tài)鏈接并直接調(diào)用指定本地方法。
虛擬機(jī)規(guī)范對(duì)本地方法棧中方法的語言與數(shù)據(jù)結(jié)構(gòu)無強(qiáng)制規(guī)定,虛擬機(jī)可自由實(shí)現(xiàn),例如 HotSpot 將虛 擬機(jī)棧和本地方法棧合二為一。
本地方法棧在棧深度異常和棧擴(kuò)展失敗時(shí)分別拋出 StackOverflowError 和 OutOfMemoryError。

📟 Q5:堆的作用是什么?

堆是虛擬機(jī)所管理的內(nèi)存中最大的一塊,被所有線程共享的,在虛擬機(jī)啟動(dòng)時(shí)創(chuàng)建。堆用來存放對(duì)象實(shí) 例,Java 里幾乎所有對(duì)象實(shí)例都在堆分配內(nèi)存。堆可以處于物理上不連續(xù)的內(nèi)存空間,邏輯上應(yīng)該連 續(xù),但對(duì)于例如數(shù)組這樣的大對(duì)象,多數(shù)虛擬機(jī)實(shí)現(xiàn)出于簡(jiǎn)單、存儲(chǔ)高效的考慮會(huì)要求連續(xù)的內(nèi)存空間。
堆既可以被實(shí)現(xiàn)成固定大小,也可以是可擴(kuò)展的,可通過 -Xms 和 -Xmx 設(shè)置堆的最小和最大容量,當(dāng)前主流 JVM 都按照可擴(kuò)展實(shí)現(xiàn)。如果堆沒有內(nèi)存完成實(shí)例分配也無法擴(kuò)展,拋出 OutOfMemoryError。

📟 Q6:方法區(qū)的作用是什么?

方法區(qū)用于存儲(chǔ)被虛擬機(jī)加載的類型信息、常量、靜態(tài)變量、即時(shí)編譯器編譯后的代碼緩存等數(shù)據(jù)。
JDK8 之前使用永久代實(shí)現(xiàn)方法區(qū),容易內(nèi)存溢出,因?yàn)橛谰么?-XX:MaxPermSize 上限,即使不設(shè) 置也有默認(rèn)大小。JDK7 把放在永久代的字符串常量池、靜態(tài)變量等移出,JDK8 中永久代完全廢棄,改 用在本地內(nèi)存中實(shí)現(xiàn)的元空間代替,把 JDK 7 中永久代剩余內(nèi)容(主要是類型信息)全部移到元空間。
虛擬機(jī)規(guī)范對(duì)方法區(qū)的約束寬松,除和堆一樣不需要連續(xù)內(nèi)存和可選擇固定大小/可擴(kuò)展外,還可以不實(shí) 現(xiàn)垃圾回收。垃圾回收在方法區(qū)出現(xiàn)較少,主要目標(biāo)針對(duì)常量池和類型卸載。如果方法區(qū)無法滿足新的 內(nèi)存分配需求,將拋出 OutOfMemoryError。

📟 Q7:運(yùn)行時(shí)常量池的作用是什么?

運(yùn)行時(shí)常量池是方法區(qū)的一部分,Class 文件中除了有類的版本、字段、方法、接口等描述信息外,還 有一項(xiàng)信息是常量池表,用于存放編譯器生成的各種字面量與符號(hào)引用,這部分內(nèi)容在類加載后存放到 運(yùn)行時(shí)常量池。一般除了保存 Class 文件中描述的符號(hào)引用外,還會(huì)把符號(hào)引用翻譯的直接引用也存儲(chǔ) 在運(yùn)行時(shí)常量池。
運(yùn)行時(shí)常量池相對(duì)于 Class 文件常量池的一個(gè)重要特征是動(dòng)態(tài)性,Java 不要求常量只有編譯期才能產(chǎn) 生,運(yùn)行期間也可以將新的常量放入池中,這種特性利用較多的是String的intern方法。
運(yùn)行時(shí)常量池是方法區(qū)的一部分,受到方法區(qū)內(nèi)存的限制,當(dāng)常量池?zé)o法再申請(qǐng)到內(nèi)存時(shí)會(huì)拋出 OutOfMemoryError。

📟 Q8:直接內(nèi)存是什么?

直接內(nèi)存不屬于運(yùn)行時(shí)數(shù)據(jù)區(qū),也不是虛擬機(jī)規(guī)范定義的內(nèi)存區(qū)域,但這部分內(nèi)存被頻繁使用,而且可能導(dǎo)致內(nèi)存溢出。
JDK1.4 中新加入了 NIO 這種基于通道與緩沖區(qū)的 IO,它可以使用 Native 函數(shù)庫直接分配堆外內(nèi)存, 通過一個(gè)堆里的 DirectByteBuffer 對(duì)象作為內(nèi)存的引用進(jìn)行操作,避免了在 Java 堆和 Native堆來回復(fù) 制數(shù)據(jù)。
直接內(nèi)存的分配不受 Java 堆大小的限制,但還是會(huì)受到本機(jī)總內(nèi)存及處理器尋址空間限制,一般配置 虛擬機(jī)參數(shù)時(shí)會(huì)根據(jù)實(shí)際內(nèi)存設(shè)置 -Xmx 等參數(shù)信息,但經(jīng)常忽略直接內(nèi)存,使內(nèi)存區(qū)域總和大于物理 內(nèi)存限制,導(dǎo)致動(dòng)態(tài)擴(kuò)展時(shí)出現(xiàn) OOM。
由直接內(nèi)存導(dǎo)致的內(nèi)存溢出,一個(gè)明顯的特征是在 Heap Dump 文件中不會(huì)看?明顯的異常,如果發(fā)現(xiàn) 內(nèi)存溢出后產(chǎn)生的 Dump 文件很小,而程序中又直接或間接使用了直接內(nèi)存(典型的間接使用就是 NIO),那么就可以考慮檢查直接內(nèi)存方面的原因。

📟 Q9:內(nèi)存溢出和內(nèi)存泄漏的區(qū)別?

內(nèi)存溢出 OutOfMemory,指程序在申請(qǐng)內(nèi)存時(shí),沒有足夠的內(nèi)存空間供其使用。
內(nèi)存泄露 Memory Leak,指程序在申請(qǐng)內(nèi)存后,無法釋放已申請(qǐng)的內(nèi)存空間,內(nèi)存泄漏最終將導(dǎo)致內(nèi) 存溢出。

📟 Q10:堆溢出的原因?

堆用于存儲(chǔ)對(duì)象實(shí)例,只要不斷創(chuàng)建對(duì)象并保證 GC Roots 到對(duì)象有可達(dá)路徑避免垃圾回收,隨著對(duì)象數(shù)量的增加,總?cè)萘坑|及最大堆容量后就會(huì) OOM,例如在 while 死循環(huán)中一直 new 創(chuàng)建實(shí)例。
堆 OOM 是實(shí)際應(yīng)用中最常?的 OOM,處理方法是通過內(nèi)存映像分析工具對(duì) Dump 出的堆轉(zhuǎn)儲(chǔ)快照分析,確認(rèn)內(nèi)存中導(dǎo)致 OOM 的對(duì)象是否必要,分清到底是內(nèi)存泄漏還是內(nèi)存溢出。 如果是內(nèi)存泄漏,通過工具查看泄漏對(duì)象到 GC Roots 的引用鏈,找到泄露對(duì)象是通過怎樣的引用路徑、與哪些 GC Roots 關(guān)聯(lián)才導(dǎo)致無法回收,一般可以準(zhǔn)確定位到產(chǎn)生內(nèi)存泄漏代碼的具***置。
如果不是內(nèi)存泄漏,即內(nèi)存中對(duì)象都必須存活,應(yīng)當(dāng)檢查 JVM 堆參數(shù),與機(jī)器內(nèi)存相比是否還有向上調(diào) 整的空間。再?gòu)拇a檢查是否存在某些對(duì)象生命周期過?、持有狀態(tài)時(shí)間過?、存儲(chǔ)結(jié)構(gòu)設(shè)計(jì)不合理等 情況,盡量減少程序運(yùn)行期的內(nèi)存消耗。

📟 Q11:棧溢出的原因?

由于 HotSpot 不區(qū)分虛擬機(jī)和本地方法棧,設(shè)置本地方法棧大小的參數(shù)沒有意義,棧容量只能由 -Xss
參數(shù)來設(shè)定,存在兩種異常:
StackOverflowError: 如果線程請(qǐng)求的棧深度大于虛擬機(jī)所允許的深度,將拋出 StackOverflowError,例如一個(gè)遞歸方法不斷調(diào)用自己。該異常有明確錯(cuò)誤堆棧可供分析,容易定位到 問題所在。
OutOfMemoryError: 如果 JVM ??梢詣?dòng)態(tài)擴(kuò)展,當(dāng)擴(kuò)展無法申請(qǐng)到足夠內(nèi)存時(shí)會(huì)拋出 OutOfMemoryError。HotSpot 不支持虛擬機(jī)棧擴(kuò)展,所以除非在創(chuàng)建線程申請(qǐng)內(nèi)存時(shí)就因無法獲得足 夠內(nèi)存而出現(xiàn) OOM,否則在線程運(yùn)行時(shí)是不會(huì)因?yàn)閿U(kuò)展而導(dǎo)致溢出的。

📟 Q12:運(yùn)行時(shí)常量池溢出的原因?

String 的 intern 方法是一個(gè)本地方法,作用是如果字符串常量池中已包含一個(gè)等于此 String 對(duì)象的 字符串,則返回池中這個(gè)字符串的 String 對(duì)象的引用,否則將此 String 對(duì)象包含的字符串添加到常量 池并返回此 String 對(duì)象的引用。
在 JDK6 及之前常量池分配在永久代,因此可以通過 -XX:PermSize 和 -XX:MaxPermSize 限制永久 代大小,間接限制常量池。在 while 死循環(huán)中調(diào)用 intern 方法導(dǎo)致運(yùn)行時(shí)常量池溢出。在 JDK7 后不 會(huì)出現(xiàn)該問題,因?yàn)榇娣旁谟谰么淖址A砍匾呀?jīng)被移至堆中。

📟 Q13:方法區(qū)溢出的原因?

方法區(qū)主要存放類型信息,如類名、訪問修飾符、常量池、字段描述、方法描述等。只要不斷在運(yùn)行時(shí)產(chǎn)生 大量類,方法區(qū)就會(huì)溢出。例如使用 JDK 反射或 CGLib 直接操作字節(jié)碼在運(yùn)行時(shí)生成大量的類。很多框 架如 Spring、Hibernate 等對(duì)類增強(qiáng)時(shí)都會(huì)使用 CGLib 這類字節(jié)碼技術(shù),增強(qiáng)的類越多就需要越大的方法區(qū)保證動(dòng)態(tài)生成的新類型可以載入內(nèi)存,也就更容易導(dǎo)致方法區(qū)溢出。
JDK8 使用元空間取代永久代,HotSpot 提供了一些參數(shù)作為元空間防御措施,例如 - XX:MetaspaceSize 指定元空間初始大小,達(dá)到該值會(huì)觸發(fā)GC進(jìn)行類型卸載,同時(shí)收集器會(huì)對(duì)該值進(jìn) 行調(diào)整,如果釋放大量空間就適當(dāng)降低該值,如果釋放很少空間就適當(dāng)提高。

📟 Q14:創(chuàng)建對(duì)象的過程是什么? 字節(jié)碼?度

NEW: 如果找不到 Class 對(duì)象則進(jìn)行類加載。加載成功后在堆中分配內(nèi)存,從 Object 到本類路徑 上的所有屬性都要分配。分配完畢后進(jìn)行零值設(shè)置。最后將指向?qū)嵗龑?duì)象的引用變量壓入虛擬機(jī)棧頂。
DUP: 在棧頂復(fù)制引用變量,這時(shí)棧頂有兩個(gè)指向堆內(nèi)實(shí)例的引用變量。兩個(gè)引用變量的目的不 同,棧底的引用用于賦值或保存局部變量表,棧頂?shù)囊米鳛榫浔{(diào)用相關(guān)方法。 INVOKESPECIAL: 通過棧頂?shù)囊米兞空{(diào)用 init 方法。
執(zhí)行?度

  1. 當(dāng) JVM 遇到字節(jié)碼 new 指令時(shí),首先將檢查該指令的參數(shù)能否在常量池中定位到一個(gè)類的符號(hào)引 用,并檢查引用代表的類是否已被加載、解析和初始化,如果沒有就先執(zhí)行類加載。
  2. 在類加載檢查通過后虛擬機(jī)將為新生對(duì)象分配內(nèi)存。
  3. 內(nèi)存分配完成后虛擬機(jī)將成員變量設(shè)為零值,保證對(duì)象的實(shí)例字段可以不賦初值就使用。
  4. 設(shè)置對(duì)象頭,包括哈希碼、GC 信息、鎖信息、對(duì)象所屬類的類元信息等。
  5. 執(zhí)行 init 方法,初始化成員變量,執(zhí)行實(shí)例化代碼塊,調(diào)用類的構(gòu)造方法,并把堆內(nèi)對(duì)象的首地址賦 值給引用變量。

📟 Q15:對(duì)象分配內(nèi)存的方式有哪些?

對(duì)象所需內(nèi)存大小在類加載完成后便可完全確定,分配空間的任務(wù)實(shí)際上等于把一塊確定大小的內(nèi)存塊從 Java 堆中劃分出來。
指針碰撞: 假設(shè) Java 堆內(nèi)存規(guī)整,被使用過的內(nèi)存放在一邊,空閑的放在另一邊,中間放著一個(gè)指針作為分界指示器,分配內(nèi)存就是把指針向空閑方向挪動(dòng)一段與對(duì)象大小相等的距離。
空閑列表: 如果 Java 堆內(nèi)存不規(guī)整,虛擬機(jī)必須維護(hù)一個(gè)列表記錄哪些內(nèi)存可用,在分配時(shí)從列表中 找到一塊足夠大的空間劃分給對(duì)象并更新列表記錄。
選擇哪種分配方式由堆是否規(guī)整決定,堆是否規(guī)整由垃圾收集器是否有空間壓縮能力決定。使用 Serial、ParNew 等收集器時(shí),系統(tǒng)采用指針碰撞;使用 CMS 這種基于清除算法的垃圾收集器時(shí),采用 空間列表。

📟 Q16:對(duì)象分配內(nèi)存是否線程安全?

對(duì)象創(chuàng)建十分頻繁,即使修改一個(gè)指針的位置在并發(fā)下也不是線程安全的,可能正給對(duì)象 A 分配內(nèi)存,指針還沒來得及修改,對(duì)象 B 又使用了指針來分配內(nèi)存。
解決方法:1 CAS 加失敗重試保證更新原子性。2 把內(nèi)存分配按線程劃分在不同空間,即每個(gè)線程在 Java 堆中預(yù)先分配一小塊內(nèi)存,叫做本地線程分配緩沖 TLAB,哪個(gè)線程要分配內(nèi)存就在對(duì)應(yīng)的 TLAB 分配,TLAB 用完了再進(jìn)行同步。

📟 Q17:對(duì)象的內(nèi)存布局了解嗎?

對(duì)象在堆內(nèi)存的存儲(chǔ)布局可分為對(duì)象頭、實(shí)例數(shù)據(jù)和對(duì)?填充。
對(duì)象頭占 12B,包括對(duì)象標(biāo)記和類型指針。對(duì)象標(biāo)記存儲(chǔ)對(duì)象自身的運(yùn)行時(shí)數(shù)據(jù),如哈希碼、GC 分代 年齡、鎖標(biāo)志、偏向線程 ID 等,這部分占 8B,稱為 Mark Word。Mark Word 被設(shè)計(jì)為動(dòng)態(tài)數(shù)據(jù)結(jié) 構(gòu),以便在極小的空間存儲(chǔ)更多數(shù)據(jù),根據(jù)對(duì)象狀態(tài)復(fù)用存儲(chǔ)空間。
類型指針是對(duì)象指向它的類型元數(shù)據(jù)的指針,占 4B。JVM 通過該指針來確定對(duì)象是哪個(gè)類的實(shí)例。
實(shí)例數(shù)據(jù)是對(duì)象真正存儲(chǔ)的有效信息,即本類對(duì)象的實(shí)例成員變量和所有可?的父類成員變量。存儲(chǔ)順 序會(huì)受到虛擬機(jī)分配策略參數(shù)和字段在源碼中定義順序的影響。相同寬度的字段總是被分配到一起存 放,在滿足該前提條件的情況下父類中定義的變量會(huì)出現(xiàn)在子類之前。
對(duì)?填充不是必然存在的,僅起占位符作用。虛擬機(jī)的自動(dòng)內(nèi)存管理系統(tǒng)要求任何對(duì)象的大小必須是 8B 的倍數(shù),對(duì)象頭已被設(shè)為 8B 的 1 或 2 倍,如果對(duì)象實(shí)例數(shù)據(jù)部分沒有對(duì)?,需要對(duì)?填充補(bǔ)全。

📟 Q18:對(duì)象的訪問方式有哪些?

Java 程序會(huì)通過棧上的 reference 引用操作堆對(duì)象,訪問方式由虛擬機(jī)決定,主流訪問方式主要有句柄和直接指針。
句柄: 堆會(huì)劃分出一塊內(nèi)存作為句柄池,reference 中存儲(chǔ)對(duì)象的句柄地址,句柄包含對(duì)象實(shí)例數(shù)據(jù)與 類型數(shù)據(jù)的地址信息。優(yōu)點(diǎn)是 reference 中存儲(chǔ)的是穩(wěn)定句柄地址,在 GC 過程中對(duì)象被移動(dòng)時(shí)只會(huì)改 變句柄的實(shí)例數(shù)據(jù)指針,而 reference 本身不需要修改。
直接指針: 堆中對(duì)象的內(nèi)存布局就必須考慮如何放置訪問類型數(shù)據(jù)的相關(guān)信息,reference 存儲(chǔ)對(duì)象地 址,如果只是訪問對(duì)象本身就不需要多一次間接訪問的開銷。優(yōu)點(diǎn)是速度更快,節(jié)省了一次指針定位的 時(shí)間開銷,HotSpot 主要使用直接指針進(jìn)行對(duì)象訪問。

📟 Q19:如何判斷對(duì)象是否是垃圾?

引用計(jì)數(shù):在對(duì)象中添加一個(gè)引用計(jì)數(shù)器,如果被引用計(jì)數(shù)器加 1,引用失效時(shí)計(jì)數(shù)器減 1,如果計(jì)數(shù) 器為 0 則被標(biāo)記為垃圾。原理簡(jiǎn)單,效率高,但是在 Java 中很少使用,因?yàn)榇嬖趯?duì)象間循環(huán)引用的問 題,導(dǎo)致計(jì)數(shù)器無法清零。
可達(dá)性分析:主流語言的內(nèi)存管理都使用可達(dá)性分析判斷對(duì)象是否存活?;舅悸肥峭ㄟ^一系列稱為GC Roots 的根對(duì)象作為起始節(jié)點(diǎn)集,從這些節(jié)點(diǎn)開始,根據(jù)引用關(guān)系向下搜索,搜索過程走過的路徑 稱為引用鏈,如果某個(gè)對(duì)象到 GC Roots 沒有任何引用鏈相連,則會(huì)被標(biāo)記為垃圾。可作為 GC Roots 的對(duì)象包括虛擬機(jī)棧和本地方法棧中引用的對(duì)象、類靜態(tài)屬性引用的對(duì)象、常量引用的對(duì)象。

📟 Q20:Java 的引用有哪些類型?

JDK1.2 后對(duì)引用進(jìn)行了擴(kuò)充,按強(qiáng)度分為四種:
強(qiáng)引用: 最常?的引用,例如 Object obj = new Object() 就屬于強(qiáng)引用。只要對(duì)象有強(qiáng)引用指向 且 GC Roots 可達(dá),在內(nèi)存回收時(shí)即使瀕臨內(nèi)存耗盡也不會(huì)被回收。
軟引用: 弱于強(qiáng)引用,描述非必需對(duì)象。在系統(tǒng)將發(fā)生內(nèi)存溢出前,會(huì)把軟引用關(guān)聯(lián)的對(duì)象加入回收范圍 以獲得更多內(nèi)存空間。用來緩存服務(wù)器中間計(jì)算結(jié)果及不需要實(shí)時(shí)保存的用戶行為等。
弱引用: 弱于軟引用,描述非必需對(duì)象。弱引用關(guān)聯(lián)的對(duì)象只能生存到下次 YGC 前,當(dāng)垃圾收集器開 始工作時(shí)無論當(dāng)前內(nèi)存是否足夠都會(huì)回收只被弱引用關(guān)聯(lián)的對(duì)象。由于 YGC 具有不確定性,因此弱引
用何時(shí)被回收也不確定。
虛引用: 最弱的引用,定義完成后無法通過該引用獲取對(duì)象。唯一目的就是為了能在對(duì)象被回收時(shí)收到 一個(gè)系統(tǒng)通知。虛引用必須與引用隊(duì)列聯(lián)合使用,垃圾回收時(shí)如果出現(xiàn)虛引用,就會(huì)在回收對(duì)象前把這 個(gè)虛引用加入引用隊(duì)列。

📟 Q21:有哪些 GC 算法?

標(biāo)記-清除算法
分為標(biāo)記和清除階段,首先從每個(gè) GC Roots 出發(fā)依次標(biāo)記有引用關(guān)系的對(duì)象,最后清除沒有標(biāo)記的對(duì) 象。
執(zhí)行效率不穩(wěn)定,如果堆包含大量對(duì)象且大部分需要回收,必須進(jìn)行大量標(biāo)記清除,導(dǎo)致效率隨對(duì)象數(shù) 量增?而降低。
存在內(nèi)存空間碎片化問題,會(huì)產(chǎn)生大量不連續(xù)的內(nèi)存碎片,導(dǎo)致以后需要分配大對(duì)象時(shí)容易觸發(fā) Full GC。
標(biāo)記-復(fù)制算法
為了解決內(nèi)存碎片問題,將可用內(nèi)存按容量劃分為大小相等的兩塊,每次只使用其中一塊。當(dāng)使用的這 塊空間用完了,就將存活對(duì)象復(fù)制到另一塊,再把已使用過的內(nèi)存空間一次清理掉。主要用于進(jìn)行新生 代。
實(shí)現(xiàn)簡(jiǎn)單、運(yùn)行高效,解決了內(nèi)存碎片問題。 代價(jià)是可用內(nèi)存縮小為原來的一半,浪費(fèi)空間。
HotSpot 把新生代劃分為一塊較大的 Eden 和兩塊較小的 Survivor,每次分配內(nèi)存只使用 Eden 和其中 一塊 Survivor。垃圾收集時(shí)將 Eden 和 Survivor 中仍然存活的對(duì)象一次性復(fù)制到另一塊 Survivor 上, 然后直接清理掉 Eden 和已用過的那塊 Survivor。HotSpot 默認(rèn)Eden 和 Survivor 的大小比例是 8:1, 即每次新生代中可用空間為整個(gè)新生代的 90%。
標(biāo)記-整理算法 標(biāo)記-復(fù)制算法在對(duì)象存活率高時(shí)要進(jìn)行較多復(fù)制操作,效率低。如果不想浪費(fèi)空間,就需要有額外空間
分配擔(dān)保,應(yīng)對(duì)被使用內(nèi)存中所有對(duì)象都存活的極端情況,所以老年代一般不使用此算法。 老年代使用標(biāo)記-整理算法,標(biāo)記過程與標(biāo)記-清除算法一樣,但不直接清理可回收對(duì)象,而是讓所有存
活對(duì)象都向內(nèi)存空間一端移動(dòng),然后清理掉邊界以外的內(nèi)存。
標(biāo)記-清除與標(biāo)記-整理的差異在于前者是一種非移動(dòng)式算法而后者是移動(dòng)式的。如果移動(dòng)存活對(duì)象,尤 其是在老年代這種每次回收都有大量對(duì)象存活的區(qū)域,是一種極為負(fù)重的操作,而且移動(dòng)必須全程暫停
用戶線程。如果不移動(dòng)對(duì)象就會(huì)導(dǎo)致空間碎片問題,只能依賴更復(fù)雜的內(nèi)存分配器和訪問器解決。

📟 Q22:你知道哪些垃圾收集器?

Serial
最基礎(chǔ)的收集器,使用復(fù)制算法、單線程工作,只用一個(gè)處理器或一條線程完成垃圾收集,進(jìn)行垃圾收 集時(shí)必須暫停其他所有工作線程。
Serial 是虛擬機(jī)在客戶端模式的默認(rèn)新生代收集器,簡(jiǎn)單高效,對(duì)于內(nèi)存受限的環(huán)境它是所有收集器中額 外內(nèi)存消耗最小的,對(duì)于處理器核心較少的環(huán)境,Serial 由于沒有線程交互開銷,可獲得最高的單線程 收集效率。
ParNew
Serial 的多線程版本,除了使用多線程進(jìn)行垃圾收集外其余行為完全一致。ParNew 是虛擬機(jī)在服務(wù)端模式的默認(rèn)新生代收集器,一個(gè)重要原因是除了 Serial 外只有它能與 CMS配合。自從 JDK 9 開始,ParNew 加 CMS 不再是官方推薦的解決方案,官方希望它被 G1 取代。 Parallel Scavenge新生代收集器,基于復(fù)制算法,是可并行的多線程收集器,與 ParNew 類似。 特點(diǎn)是它的關(guān)注點(diǎn)與其他收集器不同,Parallel Scavenge 的目標(biāo)是達(dá)到一個(gè)可控制的吞吐量,吞吐量就是處理器用于運(yùn)行用戶代碼的時(shí)間與處理器消耗總時(shí)間的比值。
Serial Old
Serial 的老年代版本,單線程工作,使用標(biāo)記-整理算法。
Serial Old 是虛擬機(jī)在客戶端模式的默認(rèn)老年代收集器,用于服務(wù)端有兩種用途:1 JDK5 及之前與Parallel Scavenge 搭配。2 作為CMS 失敗預(yù)案。 Parellel OldParallel Scavenge 的老年代版本,支持多線程,基于標(biāo)記-整理算法。JDK6 提供,注重吞吐量可考慮 Parallel Scavenge 加 Parallel Old。
CMS
以獲取最短回收停頓時(shí)間為目標(biāo),基于標(biāo)記-清除算法,過程相對(duì)復(fù)雜,分為四個(gè)步驟:初始標(biāo)記、并發(fā) 標(biāo)記、重新標(biāo)記、并發(fā)清除。初始標(biāo)記和重新標(biāo)記需要 STW(Stop The World,系統(tǒng)停頓),初始標(biāo)記僅是標(biāo)記 GC Roots 能直接關(guān) 聯(lián)的對(duì)象,速度很快。并發(fā)標(biāo)記從 GC Roots 的直接關(guān)聯(lián)對(duì)象開始遍歷整個(gè)對(duì)象圖,耗時(shí)較?但不需要 停頓用戶線程。重新標(biāo)記則是為了修正并發(fā)標(biāo)記期間因用戶程序運(yùn)作而導(dǎo)致標(biāo)記產(chǎn)生變動(dòng)的那部分記 錄。并發(fā)清除清理標(biāo)記階段判斷的已死亡對(duì)象,不需要移動(dòng)存活對(duì)象,該階段也可與用戶線程并發(fā)。
缺點(diǎn):1 對(duì)處理器資源敏感,并發(fā)階段雖然不會(huì)導(dǎo)致用戶線程暫停,但會(huì)降低吞吐量。2 無法處理浮動(dòng) 垃圾,有可能出現(xiàn)并發(fā)失敗而導(dǎo)致 Full GC。3 基于標(biāo)記-清除算法,產(chǎn)生空間碎片。
G1
開創(chuàng)了收集器面向局部收集的設(shè)計(jì)思路和基于 Region 的內(nèi)存布局,主要面向服務(wù)端,最初設(shè)計(jì)目標(biāo)是 替換 CMS。
G1 之前的收集器,垃圾收集目標(biāo)要么是整個(gè)新生代,要么是整個(gè)老年代或整個(gè)堆。而 G1 可面向堆任何 部分來組成回收集進(jìn)行回收,衡量標(biāo)準(zhǔn)不再是分代,而是哪塊內(nèi)存中存放的垃圾數(shù)量最多,回收受益最大。
跟蹤各 Region 里垃圾的價(jià)值,價(jià)值即回收所獲空間大小以及回收所需時(shí)間的經(jīng)驗(yàn)值,在后臺(tái)維護(hù)一個(gè) 優(yōu)先級(jí)列表,每次根據(jù)用戶設(shè)定允許的收集停頓時(shí)間優(yōu)先處理回收價(jià)值最大的 Region。這種方式保證 了 G1 在有限時(shí)間內(nèi)獲取盡可能高的收集效率。
G1 運(yùn)作過程:
初始標(biāo)記:標(biāo)記 GC Roots 能直接關(guān)聯(lián)到的對(duì)象,讓下一階段用戶線程并發(fā)運(yùn)行時(shí)能正確地在可用Region 中分配新對(duì)象。需要 STW 但耗時(shí)很短,在 Minor GC 時(shí)同步完成。
并發(fā)標(biāo)記:從 GC Roots 開始對(duì)堆中對(duì)象進(jìn)行可達(dá)性分析,遞歸掃描整個(gè)堆的對(duì)象圖。耗時(shí)?但可 與用戶線程并發(fā),掃描完成后要重新處理 SATB 記錄的在并發(fā)時(shí)有變動(dòng)的對(duì)象。 最終標(biāo)記:對(duì)用戶線程做短暫暫停,處理并發(fā)階段結(jié)束后仍遺留下來的少量 SATB 記錄。 篩選回收:對(duì)各 Region 的回收價(jià)值排序,根據(jù)用戶期望停頓時(shí)間制定回收計(jì)劃。必須暫停用戶線 程,由多條收集線程并行完成。
可由用戶指定期望停頓時(shí)間是 G1 的一個(gè)強(qiáng)大功能,但該值不能設(shè)得太低,一般設(shè)置為100~300 ms。

📟 Q23:ZGC 了解嗎?

JDK11 中加入的具有實(shí)驗(yàn)性質(zhì)的低延遲垃圾收集器,目標(biāo)是盡可能在不影響吞吐量的前提下,實(shí)現(xiàn)在任意堆內(nèi)存大小都可以把停頓時(shí)間限制在 10ms 以內(nèi)的低延遲。
基于 Region 內(nèi)存布局,不設(shè)分代,使用了讀屏障、染色指針和內(nèi)存多重映射等技術(shù)實(shí)現(xiàn)可并發(fā)的標(biāo)記- 整理,以低延遲為首要目標(biāo)。
ZGC 的 Region 具有動(dòng)態(tài)性,是動(dòng)態(tài)創(chuàng)建和銷毀的,并且容量大小也是動(dòng)態(tài)變化的。

📟 Q24:你知道哪些內(nèi)存分配與回收策略?

對(duì)象優(yōu)先在 Eden 區(qū)分配
大多數(shù)情況下對(duì)象在新生代 Eden 區(qū)分配,當(dāng) Eden 沒有足夠空間時(shí)將發(fā)起一次 Minor GC。
大對(duì)象直接進(jìn)入老年代
大對(duì)象指需要大量連續(xù)內(nèi)存空間的對(duì)象,典型是很?的字符串或數(shù)量龐大的數(shù)組。大對(duì)象容易導(dǎo)致內(nèi)存 還有不少空間就提前觸發(fā)垃圾收集以獲得足夠的連續(xù)空間。
HotSpot 提供了 -XX:PretenureSizeThreshold 參數(shù),大于該值的對(duì)象直接在老年代分配,避免在Eden 和 Survivor 間來回復(fù)制。
?期存活對(duì)象進(jìn)入老年代
虛擬機(jī)給每個(gè)對(duì)象定義了一個(gè)對(duì)象年齡計(jì)數(shù)器,存儲(chǔ)在對(duì)象頭。如果經(jīng)歷過第一次 Minor GC 仍然存活 且能被 Survivor 容納,該對(duì)象就會(huì)被移動(dòng)到 Survivor 中并將年齡設(shè)置為 1。對(duì)象在 Survivor 中每熬過一次 Minor GC 年齡就加 1 ,當(dāng)增加到一定程度(默認(rèn)15)就會(huì)被晉升到老年代。對(duì)象晉升老年代的閾 值可通過 -XX:MaxTenuringThreshold 設(shè)置。
動(dòng)態(tài)對(duì)象年齡判定
為了適應(yīng)不同內(nèi)存狀況,虛擬機(jī)不要求對(duì)象年齡達(dá)到閾值才能晉升老年代,如果在 Survivor 中相同年齡 所有對(duì)象大小的總和大于 Survivor 的一半,年齡不小于該年齡的對(duì)象就可以直接進(jìn)入老年代。
空間分配擔(dān)保
MinorGC 前虛擬機(jī)必須檢查老年代最大可用連續(xù)空間是否大于新生代對(duì)象總空間,如果滿足則說明這 次 Minor GC 確定安全。
如果不滿足,虛擬機(jī)會(huì)查看 -XX:HandlePromotionFailure 參數(shù)是否允許擔(dān)保失敗,如果允許會(huì)繼 續(xù)檢查老年代最大可用連續(xù)空間是否大于歷次晉升老年代對(duì)象的平均大小,如果滿足將冒險(xiǎn)嘗試一次 Minor GC,否則改成一次 FullGC。
冒險(xiǎn)是因?yàn)樾律褂脧?fù)制算法,為了內(nèi)存利用率只使用一個(gè) Survivor,大量對(duì)象在 Minor GC 后仍然 存活時(shí),需要老年代進(jìn)行分配擔(dān)保,接收 Survivor 無法容納的對(duì)象。

📟 Q25:你知道哪些故障處理工具?

jps:虛擬機(jī)進(jìn)程狀況工具
功能和 ps 命令類似:可以列出正在運(yùn)行的虛擬機(jī)進(jìn)程,顯示虛擬機(jī)執(zhí)行主類名稱以及這些進(jìn)程的本地 虛擬機(jī)唯一 ID(LVMID)。LVMID 與操作系統(tǒng)的進(jìn)程 ID(PID)一致,使用 Windows 的任務(wù)管理器或 UNIX 的 ps 命令也可以查詢到虛擬機(jī)進(jìn)程的 LVMID,但如果同時(shí)啟動(dòng)了多個(gè)虛擬機(jī)進(jìn)程,必須依賴 jps 命令。
jstat:虛擬機(jī)統(tǒng)計(jì)信息監(jiān)視工具 用于監(jiān)視虛擬機(jī)各種運(yùn)行狀態(tài)信息。可以顯示本地或遠(yuǎn)程虛擬機(jī)進(jìn)程中的類加載、內(nèi)存、垃圾收集、即時(shí)編譯器等運(yùn)行時(shí)數(shù)據(jù),在沒有 GUI 界面的服務(wù)器上是運(yùn)行期定位虛擬機(jī)性能問題的常用工具。 參數(shù)含義:S0 和 S1 表示兩個(gè) Survivor,E 表示新生代,O 表示老年代,YGC 表示 Young GC 次數(shù),
YGCT 表示 Young GC 耗時(shí),FGC 表示 Full GC 次數(shù),FGCT 表示 Full GC 耗時(shí),GCT 表示 GC 總耗時(shí)。 jinfo:Java 配置信息工具實(shí)時(shí)查看和調(diào)整虛擬機(jī)各項(xiàng)參數(shù),使用 jps 的 -v 參數(shù)可以查看虛擬機(jī)啟動(dòng)時(shí)顯式指定的參數(shù),但如果想 知道未顯式指定的參數(shù)值只能使用 jinfo 的 -flag 查詢。
jmap:Java 內(nèi)存映像工具
用于生成堆轉(zhuǎn)儲(chǔ)快照,還可以查詢 finalize 執(zhí)行隊(duì)列、Java 堆和方法區(qū)的詳細(xì)信息,如空間使用率,當(dāng) 前使用的是哪種收集器等。和 jinfo 一樣,部分功能在 Windows 受限,除了生成堆轉(zhuǎn)儲(chǔ)快照的 -dump 和查看每個(gè)類實(shí)例的 -histo 外,其余選項(xiàng)只能在 Linux 使用。
jhat:虛擬機(jī)堆轉(zhuǎn)儲(chǔ)快照分析工具
JDK 提供 jhat 與 jmap 搭配使用分析 jmap 生成的堆轉(zhuǎn)儲(chǔ)快照。jhat 內(nèi)置了一個(gè)微型的 HTTP/Web 服務(wù)器,生成堆轉(zhuǎn)儲(chǔ)快照的分析結(jié)果后可以在瀏覽器查看。
jstack:Java 堆棧跟蹤工具
用于生成虛擬機(jī)當(dāng)前時(shí)刻的線程快照。線程快照就是當(dāng)前虛擬機(jī)內(nèi)每一條線程正在執(zhí)行的方法堆棧的集 合,生成線程快照的目的通常是定位線程出現(xiàn)?時(shí)間停頓的原因,如線程間死鎖、死循環(huán)、請(qǐng)求外部資 源導(dǎo)致的?時(shí)間掛起等。線程出現(xiàn)停頓時(shí)通過 jstack 查看各個(gè)線程的調(diào)用堆棧,可以獲知沒有響應(yīng)的線程 在后臺(tái)做什么或等什么資源。

📟 Q26:Java 程序是怎樣運(yùn)行的?

首先通過 Javac 編譯器將 .java 轉(zhuǎn)為 JVM 可加載的 .class 字節(jié)碼文件。
Javac 是由 Java 編寫的程序,編譯過程可以分為: 1 詞法解析,通過空格分割出單詞、操作符、 控制符等信息,形成 token 信息流,傳遞給語法解析器。2 語法解析,把 token 信息流按照 Java 語法規(guī)則組裝成語法樹。3 語義分析,檢查關(guān)鍵字使用是否合理、類型是否匹配、作用域是否正 確等。4 字節(jié)碼生成,將前面各個(gè)步驟的信息轉(zhuǎn)換為字節(jié)碼。
字節(jié)碼必須通過類加載過程加載到 JVM 后才可以執(zhí)行,執(zhí)行有三種模式,解釋執(zhí)行、JIT 編譯執(zhí) 行、JIT 編譯與解釋器混合執(zhí)行(主流 JVM 默認(rèn)執(zhí)行的方式)?;旌夏J降膬?yōu)勢(shì)在于解釋器在啟動(dòng)時(shí) 先解釋執(zhí)行,省去編譯時(shí)間。
之后通過即時(shí)編譯器 JIT 把字節(jié)碼文件編譯成本地機(jī)器碼。
Java 程序最初都是通過解釋器進(jìn)行解釋執(zhí)行的,當(dāng)虛擬機(jī)發(fā)現(xiàn)某個(gè)方法或代碼塊的運(yùn)行特別頻繁, 就會(huì)認(rèn)定其為"熱點(diǎn)代碼",熱點(diǎn)代碼的檢測(cè)主要有基于采樣和基于計(jì)數(shù)器兩種方式,為了提高 熱點(diǎn) 代碼的執(zhí)行效率,虛擬機(jī)會(huì)把它們編譯成本地機(jī)器碼,盡可能對(duì)代碼優(yōu)化,在運(yùn)行時(shí)完成這個(gè) 任務(wù)的 后端編譯器被稱為即時(shí)編譯器。
還可以通過靜態(tài)的提前編譯器 AOT 直接把程序編譯成與目標(biāo)機(jī)器指令集相關(guān)的二進(jìn)制代碼。

📟 Q27:類加載是什么?

Class 文件中描述的各類信息都需要加載到虛擬機(jī)后才能使用。JVM 把描述類的數(shù)據(jù)從 Class 文件加載 到內(nèi)存,并對(duì)數(shù)據(jù)進(jìn)行校驗(yàn)、解析和初始化,最終形成可以被虛擬機(jī)直接使用的 Java 類型,這個(gè)過程稱 為虛擬機(jī)的類加載機(jī)制。
與編譯時(shí)需要連接的語言不同,Java 中類型的加載、連接和初始化都是在運(yùn)行期間完成的,這增加了性 能開銷,但卻提供了極高的擴(kuò)展性,Java 動(dòng)態(tài)擴(kuò)展的語言特性就是依賴運(yùn)行期動(dòng)態(tài)加載和連接實(shí)現(xiàn)的。
一個(gè)類型從被加載到虛擬機(jī)內(nèi)存開始,到卸載出內(nèi)存為止,整個(gè)生命周期經(jīng)歷加載、驗(yàn)證、準(zhǔn)備、解 析、初始化、使用和卸載七個(gè)階段,其中驗(yàn)證、解析和初始化三個(gè)部分稱為連接。加載、驗(yàn)證、準(zhǔn)備、 初始化階段的順序是確定的,解析則不一定:可能在初始化之后再開始,這是為了支持 Java 的動(dòng)態(tài)綁 定。

📟 Q28:類初始化的情況有哪些?

1 遇到 new 、 getstatic 、 putstatic 或 invokestatic 字節(jié)碼指令時(shí),還未初始化。典型場(chǎng)景包括 new 實(shí)例化對(duì)象、讀取或設(shè)置靜態(tài)字段、調(diào)用靜態(tài)方法。 2 對(duì)類反射調(diào)用時(shí),還未初始化。
3 初始化類時(shí),父類還未初始化。
4 虛擬機(jī)啟動(dòng)時(shí),會(huì)先初始化包含 main 方法的主類。
5 使用 JDK7 的動(dòng)態(tài)語言支持時(shí),如果 MethodHandle 實(shí)例的解析結(jié)果為指定類型的方法句柄且句柄 對(duì)應(yīng)的類還未初始化。
6 接口定義了默認(rèn)方法,如果接口的實(shí)現(xiàn)類初始化,接口要在其之前初始化。
其余所有引用類型的方式都不會(huì)觸發(fā)初始化,稱為被動(dòng)引用。被動(dòng)引用實(shí)例:1 子類使用父類的靜態(tài)字段 時(shí),只有父類被初始化。2 通過數(shù)組定義使用類。3 常量在編譯期會(huì)存入調(diào)用類的常量池,不會(huì)初始 化定義常量的類。
接口和類加載過程的區(qū)別:初始化類時(shí)如果父類沒有初始化需要初始化父類,但接口初始化時(shí)不要求父 接口初始化,只有在真正使用父接口時(shí)(如引用接口中定義的常量)才會(huì)初始化。

📟 Q29:類加載的過程是什么? 加載

該階段虛擬機(jī)需要完成三件事:1 通過一個(gè)類的全限定類名獲取定義類的二進(jìn)制字節(jié)流。2 將字節(jié)流 所代表的靜態(tài)存儲(chǔ)結(jié)構(gòu)轉(zhuǎn)化為方法區(qū)的運(yùn)行時(shí)數(shù)據(jù)區(qū)。3 在內(nèi)存中生成對(duì)應(yīng)該類的 Class 實(shí)例,作為方 法區(qū)這個(gè)類的數(shù)據(jù)訪問入口。
驗(yàn)證
確保 Class 文件的字節(jié)流符合約束。如果虛擬機(jī)不檢查輸入的字節(jié)流,可能因?yàn)檩d入有錯(cuò)誤或惡意企圖 的字節(jié)流而導(dǎo)致系統(tǒng)受攻擊。驗(yàn)證主要包含四個(gè)階段:文件格式驗(yàn)證、元數(shù)據(jù)驗(yàn)證、字節(jié)碼驗(yàn)證、符號(hào) 引用驗(yàn)證。
驗(yàn)證重要但非必需,因?yàn)橹挥型ㄟ^與否的區(qū)別,通過后對(duì)程序運(yùn)行期沒有任何影響。如果代碼已被反復(fù) 使用和驗(yàn)證過,在生產(chǎn)環(huán)境就可以考慮關(guān)閉大部分驗(yàn)證縮短類加載時(shí)間。
準(zhǔn)備
為類靜態(tài)變量分配內(nèi)存并設(shè)置零值,該階段進(jìn)行的內(nèi)存分配僅包括類變量,不包括實(shí)例變量。如果變量 被 final 修飾,編譯時(shí) Javac 會(huì)為變量生成 ConstantValue 屬性,準(zhǔn)備階段虛擬機(jī)會(huì)將變量值設(shè)為代碼值。
解析
將常量池內(nèi)的符號(hào)引用替換為直接引用。
符號(hào)引用以一組符號(hào)描述引用目標(biāo),可以是任何形式的字面量,只要使用時(shí)能無歧義地定位目標(biāo)即可。 與虛擬機(jī)內(nèi)存布局無關(guān),引用目標(biāo)不一定已經(jīng)加載到虛擬機(jī)內(nèi)存。
直接引用是可以直接指向目標(biāo)的指針、相對(duì)偏移量或能間接定位到目標(biāo)的句柄。和虛擬機(jī)的內(nèi)存布局相 關(guān),引用目標(biāo)必須已在虛擬機(jī)的內(nèi)存中存在。
初始化
直到該階段 JVM 才開始執(zhí)行類中編寫的代碼。準(zhǔn)備階段時(shí)變量賦過零值,初始化階段會(huì)根據(jù)程序員的編 碼去初始化類變量和其他資源。初始化階段就是執(zhí)行類構(gòu)造方法中的 方法,該方法是 Javac 自動(dòng)生成的。

📟 Q30:有哪些類加載器?

自 JDK1.2 起 Java 一直保持三層類加載器: 啟動(dòng)類加載器
在 JVM 啟動(dòng)時(shí)創(chuàng)建,負(fù)責(zé)加載最核心的類,例如 Object、System 等。無法被程序直接引用,如 果需要把加載委派給啟動(dòng)類加載器,直接使用 null 代替即可,因?yàn)閱?dòng)類加載器通常由操作系統(tǒng) 實(shí)現(xiàn),并不存在于 JVM 體系。
平臺(tái)類加載器
從 JDK9 開始從擴(kuò)展類加載器更換為平臺(tái)類加載器,負(fù)載加載一些擴(kuò)展的系統(tǒng)類,比如 XML、加 密、壓縮相關(guān)的功能類等。
應(yīng)用類加載器
也稱系統(tǒng)類加載器,負(fù)責(zé)加載用戶類路徑上的類庫,可以直接在代碼中使用。如果沒有自定義類加 載器,一般情況下應(yīng)用類加載器就是默認(rèn)的類加載器。自定義類加載器通過繼承 ClassLoader 并 重寫 findClass 方法實(shí)現(xiàn)。

📟 Q31:雙親委派模型是什么?

類加載器具有等級(jí)制度但非繼承關(guān)系,以組合的方式復(fù)用父加載器的功能。雙親委派模型要求除了頂層
的啟動(dòng)類加載器外,其余類加載器都應(yīng)該有自己的父加載器。
一個(gè)類加載器收到了類加載請(qǐng)求,它不會(huì)自己去嘗試加載,而將該請(qǐng)求委派給父加載器,每層的類加載 器都是如此,因此所有加載請(qǐng)求最終都應(yīng)該傳送到啟動(dòng)類加載器,只有當(dāng)父加載器反饋無法完成請(qǐng)求 時(shí),子加載器才會(huì)嘗試。
類跟隨它的加載器一起具備了有優(yōu)先級(jí)的層次關(guān)系,確保某個(gè)類在各個(gè)類加載器環(huán)境中都是同一個(gè),保 證程序的穩(wěn)定性。

📟 Q32:如何判斷兩個(gè)類是否相等?

任意一個(gè)類都必須由類加載器和這個(gè)類本身共同確立其在虛擬機(jī)中的唯一性。
兩個(gè)類只有由同一類加載器加載才有比較意義,否則即使兩個(gè)類來源于同一個(gè) Class 文件,被同一個(gè) JVM 加載,只要類加載器不同,這兩個(gè)類就必定不相等。

寫在最后

希望博主收集的內(nèi)容能幫到大家,祝大家能找到一個(gè)好的工作,過好的生活,如有錯(cuò)誤歡迎指正。 💐💐💐

http://www.risenshineclean.com/news/60850.html

相關(guān)文章:

  • 帝國(guó)cms做中英文網(wǎng)站電商網(wǎng)站建設(shè)哪家好
  • 地方門戶網(wǎng)站建設(shè)要求福州百度分公司
  • wordpress附件插件南寧seo推廣優(yōu)化
  • 建設(shè)企業(yè)資質(zhì)雙網(wǎng)是哪兩個(gè)網(wǎng)站線上推廣平臺(tái)都有哪些
  • 福州正規(guī)網(wǎng)站建設(shè)公司報(bào)價(jià)軟文廣告案例分析
  • 酒店網(wǎng)站設(shè)計(jì)模板免費(fèi)創(chuàng)建網(wǎng)站的平臺(tái)
  • 手機(jī)微網(wǎng)站優(yōu)化大師使用心得
  • 網(wǎng)站建設(shè)聯(lián)盟深圳互聯(lián)網(wǎng)公司50強(qiáng)
  • 自適應(yīng)網(wǎng)站如何做mip網(wǎng)頁快速排名優(yōu)化seo
  • 長(zhǎng)葛網(wǎng)站建設(shè)公司最近國(guó)際新聞大事20條
  • 定制開發(fā)平臺(tái)電商網(wǎng)站seo怎么做
  • 哪個(gè)網(wǎng)站可以接任務(wù)做兼職移動(dòng)網(wǎng)站如何優(yōu)化排名
  • 網(wǎng)站開發(fā)期間賬務(wù)處理新產(chǎn)品推廣
  • 網(wǎng)站設(shè)計(jì)步驟畢業(yè)論文互聯(lián)網(wǎng)營(yíng)銷師證書怎么考多少錢
  • 湛江cms建站排名點(diǎn)擊工具
  • 千華網(wǎng)鞍山門戶網(wǎng)站關(guān)鍵詞搜索站長(zhǎng)工具
  • h5制作軟件電腦百度ocpc怎么優(yōu)化
  • 中國(guó)建設(shè)銀行北海招聘信息網(wǎng)站百度旗下產(chǎn)品
  • 視頻網(wǎng)站app怎么做的長(zhǎng)春做網(wǎng)絡(luò)優(yōu)化的公司
  • 外貿(mào)網(wǎng)站推廣計(jì)劃關(guān)鍵詞排名工具
  • 青島公司網(wǎng)站建設(shè)公司seo關(guān)鍵詞排名優(yōu)化案例
  • 網(wǎng)站如何防盜鏈網(wǎng)站運(yùn)營(yíng)策劃書范文
  • 圍場(chǎng)網(wǎng)站建設(shè)sem優(yōu)化師
  • 臨安建辦網(wǎng)站長(zhǎng)沙關(guān)鍵詞優(yōu)化平臺(tái)
  • mysql做wp網(wǎng)站什么是網(wǎng)絡(luò)營(yíng)銷公司
  • 網(wǎng)站輿情監(jiān)控怎么做運(yùn)營(yíng)推廣
  • 北京專業(yè)企業(yè)營(yíng)銷網(wǎng)站建設(shè)互聯(lián)網(wǎng)推廣是什么意思
  • 大連哪家網(wǎng)站公司好如何做好精準(zhǔn)營(yíng)銷
  • 有模塊傳奇網(wǎng)站怎么做新東方雅思培訓(xùn)價(jià)目表
  • 外貿(mào)做網(wǎng)站建設(shè)哪家好東莞網(wǎng)站優(yōu)化