欧美1区2区3区激情无套,两个女人互添下身视频在线观看,久久av无码精品人妻系列,久久精品噜噜噜成人,末发育娇小性色xxxx

深入理解Java虛擬機(jī)-類加載機(jī)制

類加載過程

加載(Loading)

  • 將類的字節(jié)碼文件(.class文件)加載到內(nèi)存,并生成對應(yīng)的Class對象(存儲(chǔ)在方法區(qū))
  • 查找字節(jié)碼:通過類的全限定名(如java.lang.String)定位字節(jié)碼文件
  • 讀取字節(jié)碼:將字節(jié)碼轉(zhuǎn)換為二進(jìn)制流
  • 生成Class對象:在方法區(qū)中創(chuàng)建類的Class對象(后續(xù)反射操作的基礎(chǔ))Class<?> clazz = Class.forName("com.example.MyClass"); // 觸發(fā)加載階段

驗(yàn)證(Verification)

  • 確保字節(jié)碼符合JVM規(guī)范,防止惡意代碼或錯(cuò)誤字節(jié)碼危害JVM安全
  • 文件格式驗(yàn)證:檢查魔數(shù)(0xCAFEBABE)和版本號(hào)是否合法,驗(yàn)證常量池中的常量類型是否有效
  • 元數(shù)據(jù)驗(yàn)證:檢查類是否有父類(除Object外)、是否繼承final類、字段/方法是否與父類沖突若一個(gè)類嘗試?yán)^承final類(如String),驗(yàn)證階段會(huì)拋出java.lang.VerifyError
  • 字節(jié)碼驗(yàn)證:確保方法體的字節(jié)碼不會(huì)導(dǎo)致JVM崩潰(如操作數(shù)棧溢出、跳轉(zhuǎn)到不存在的指令)
  • 符號(hào)引用驗(yàn)證:檢查符號(hào)引用(如類名、方法名)是否合法,確保解析階段能正確綁定

準(zhǔn)備(Preparation)

  • 為類的靜態(tài)變量(類變量)分配內(nèi)存,并設(shè)置初始值(零值)

解析(Resolution)

  • 將常量池中的符號(hào)引用轉(zhuǎn)換為直接引用(內(nèi)存地址或偏移量)
  • 符號(hào)引用:一組符號(hào)描述目標(biāo)(如java/lang/Object
  • 直接引用:指向目標(biāo)的指針、偏移量或句柄
  • 類/接口解析:將類名符號(hào)引用轉(zhuǎn)換為對應(yīng)的Class對象
  • 字段解析:將字段名轉(zhuǎn)換為內(nèi)存中的偏移量
  • 方法解析:將方法名轉(zhuǎn)換為方法入口地址
  • 解析階段可能在初始化之后觸發(fā)(如動(dòng)態(tài)綁定)

初始化(Initialization)

  • 執(zhí)行類的初始化代碼(<clinit>()方法),為靜態(tài)變量賦真實(shí)值,執(zhí)行靜態(tài)代碼塊
  • 觸發(fā)條件創(chuàng)建類的實(shí)例(new)訪問類的靜態(tài)變量(非常量)或靜態(tài)方法反射調(diào)用(如Class.forName())初始化子類時(shí),父類需先初始化JVM啟動(dòng)時(shí)指定的主類(包含main()的類)
  • 初始化順序:父類的<clinit>()先于子類執(zhí)行,靜態(tài)變量賦值和靜態(tài)代碼塊按代碼順序執(zhí)行
  • 若多個(gè)線程同時(shí)初始化一個(gè)類,JVM會(huì)保證同步(僅一個(gè)線程執(zhí)行<clinit>())

類加載總結(jié)

加載

.class

文件

Class

對象

查找字節(jié)碼,生成內(nèi)存結(jié)構(gòu)

驗(yàn)證

字節(jié)碼

合法字節(jié)碼

檢查格式、元數(shù)據(jù)、字節(jié)碼邏輯

準(zhǔn)備

靜態(tài)變量符號(hào)引用

靜態(tài)變量內(nèi)存分配(零值)

分配內(nèi)存,設(shè)置默認(rèn)值

解析

符號(hào)引用

直接引用

綁定類、字段、方法的內(nèi)存地址

初始化

靜態(tài)變量和代碼塊

類完全可用

執(zhí)行

<clinit>()

,賦真實(shí)值,執(zhí)行靜態(tài)代碼塊

常見問題與解決方案

  • 類加載失?。涸颍侯惵窂藉e(cuò)誤、字節(jié)碼損壞、版本不兼容解決:檢查-classpath配置,確認(rèn)類文件完整性
  • 靜態(tài)代碼塊死鎖:原因:多線程初始化時(shí),靜態(tài)代碼塊內(nèi)同步操作導(dǎo)致死鎖解決:避免在靜態(tài)代碼塊中使用復(fù)雜同步邏輯
  • 類重復(fù)加載:原因:不同類加載器加載同一類解決:遵循雙親委派模型,避免自定義類加載器破壞機(jī)制

類加載器

類加載器的核心作用

  • 加載字節(jié)碼:從文件系統(tǒng)、網(wǎng)絡(luò)、JAR包等來源讀取字節(jié)碼
  • 類隔離:通過不同類加載器實(shí)現(xiàn)類的命名空間隔離(如Tomcat中的Web應(yīng)用)
  • 動(dòng)態(tài)加載:支持運(yùn)行時(shí)加載類(如插件化、熱部署)
  • 安全性控制:防止惡意代碼替換核心類(如java.lang.String

啟動(dòng)類加載(Bootstrap ClassLoader)

  • 職責(zé):加載JVM核心類庫(jre/lib目錄下的rt.jar、resources.jar等)Java 9+ 加載java.base(java.lang/java.util/java.io)、java.datatransfer、java.instrument
  • 實(shí)現(xiàn):由C/C++編寫,是JVM的一部分,無Java類實(shí)例
  • 訪問限制:無法在Java代碼中直接引用(getClassLoader()返回null)

擴(kuò)展類加載器(Extension ClassLoader)/平臺(tái)類加載器(Platform ClassLoader, Java 9+)

  • 職責(zé):加載擴(kuò)展類庫(jre/lib/ext目錄下的JAR包)Java 9+ 加載java.sql、java.xml、java.logging、java.management
  • 實(shí)現(xiàn):Java類sun.misc.Launcher$ExtClassLoader
  • 父加載器:啟動(dòng)類加載器

應(yīng)用程序類加載器(Application ClassLoader)

  • 職責(zé):加載用戶類路徑(-classpathCLASSPATH環(huán)境變量)下的類
  • 實(shí)現(xiàn):Java類sun.misc.Launcher$AppClassLoader
  • 父加載器:擴(kuò)展類加載器
  • 默認(rèn)類加載器:ClassLoader.getSystemClassLoader()返回此加載器

雙親委派模型(Parent Delegation Model)

  • 委派父加載器:優(yōu)先讓父加載器嘗試加載
  • 父加載器失敗:若父加載器無法加載,自己嘗試加載。
  • 最終失?。喝羲屑虞d器無法加載,拋出ClassNotFoundException
  • 雙親委派的優(yōu)勢避免類重復(fù)加載:父加載器加載的類,子加載器不會(huì)重復(fù)加載保護(hù)核心類庫:防止用戶自定義類覆蓋核心類(如自定義java.lang.Object

自定義類加載器

  • 繼承ClassLoader:重寫findClass()方法
  • 加載字節(jié)碼:從自定義路徑(如網(wǎng)絡(luò)、加密文件)讀取字節(jié)碼
  • 定義類:調(diào)用defineClass()生成Class對象
  • 使用場景熱替換:動(dòng)態(tài)加載修改后的類(如調(diào)試環(huán)境)加密類加載:加載加密的字節(jié)碼文件模塊隔離:不同模塊使用獨(dú)立類加載器(如Tomcat的Web應(yīng)用)

Tomcat的類加載器

  • 層級(jí)結(jié)構(gòu):Common ClassLoader:加載Tomcat和Web應(yīng)用共享的類WebApp ClassLoader:每個(gè)Web應(yīng)用獨(dú)立,加載WEB-INF/classes和WEB-INF/libJSP ClassLoader:動(dòng)態(tài)加載JSP編譯后的類,支持熱替換
  • 隔離機(jī)制:不同Web應(yīng)用的類加載器相互隔離,避免類沖突

Spring的動(dòng)態(tài)代理

  • 場景:為接口生成代理類。
  • 類加載器:使用AppClassLoader加載代理類,或通過Thread.currentThread().getContextClassLoader()獲取

OSGi模塊化

  • 機(jī)制:每個(gè)Bundle(模塊)有自己的類加載器,按需動(dòng)態(tài)加載依賴
  • 優(yōu)勢:支持模塊熱插拔和版本共存

打破雙親委派

線程上下文類加載器(Thread Context ClassLoader)

  • 背景:在SPI機(jī)制中,核心接口由啟動(dòng)類加載器加載,但實(shí)現(xiàn)類需由應(yīng)用類加載器加載
  • 通過Thread.currentThread().setContextClassLoader()設(shè)置線程上下文類加載器
  • 在SPI代碼中,使用Thread.currentThread().getContextClassLoader()加載實(shí)現(xiàn)類

自定義類加載器

  • 背景:需要?jiǎng)討B(tài)加載類或?qū)崿F(xiàn)模塊化隔離
  • 繼承ClassLoader,重寫loadClass()findClass()方法,直接加載類而不委派父加載器

OSGi模塊化

  • 背景:每個(gè)模塊(Bundle)需要獨(dú)立的類加載器,支持模塊熱插拔和版本共存
  • 每個(gè)Bundle有自己的類加載器,按需加載依賴模塊
  • 通過Import-PackageExport-Package聲明模塊間的依賴關(guān)系

打破雙親委派的應(yīng)用場景

  • SPI機(jī)制:JDBC、JNDI、JAXP等服務(wù)的實(shí)現(xiàn)類需由應(yīng)用類加載器加載,使用線程上下文類加載器加載實(shí)現(xiàn)類
  • 熱部署:在開發(fā)或調(diào)試環(huán)境中,動(dòng)態(tài)替換已加載的類,自定義類加載器直接加載新版本的類,舊版本類由GC回收
  • OSGI模塊化與插件化:不同模塊或插件需要獨(dú)立的類加載器,避免類沖突,每個(gè)模塊或插件使用獨(dú)立的類加載器
全部評(píng)論

相關(guān)推薦

問題1:為什么會(huì)使用分庫分表,到達(dá)了什么樣的數(shù)據(jù)級(jí)別才會(huì)去加設(shè)計(jì),是否對數(shù)據(jù)量有一個(gè)統(tǒng)計(jì)我的理解:看星哥之前寫過&nbsp;單表行數(shù)超&nbsp;500&nbsp;萬行或者單表容量超過&nbsp;2GB,推薦分庫分表,但是面試的過程中怕被問自己寫的項(xiàng)目會(huì)有這么大的數(shù)據(jù)量嗎不要這么硬背,具體情況具體分析,有的表字段少,經(jīng)常是條件等值查詢,這樣加個(gè)索引,一個(gè)億也不用分表,有的字段多,還是范圍查詢,可能5000萬就得分表,面試官問你你說是自己在學(xué)習(xí)分庫分表應(yīng)用到項(xiàng)目中,自己造了幾千萬的數(shù)據(jù)量問題2:基因法需要分表的一個(gè)數(shù)量和確定的一個(gè)東西(我的理解是分表的依據(jù),例如大麥中是訂單編號(hào)和用戶id),但是正常的生產(chǎn)環(huán)境中是可能動(dòng)態(tài)改變的,比如說需要?jiǎng)討B(tài)擴(kuò)容的話,怎么解決呢(例如當(dāng)前有4個(gè)分表,但是現(xiàn)在需要擴(kuò)充到8個(gè)分表),是使用雙寫嗎?這個(gè)在擴(kuò)容前就要考慮好能維持多少年內(nèi)不需要再擴(kuò)容。轉(zhuǎn)轉(zhuǎn)架構(gòu)師在分庫分表前,通過之前記錄的數(shù)據(jù)增長量,做了256張表,能在7年內(nèi)不需要再擴(kuò)容,如果需要擴(kuò)容的話,可以使用雙寫,新擴(kuò)容表寫的過程中,用新的分庫分表算法問題3:如果在防止超賣的過程中,Redis不可用了,怎么解決我的理解:使用Redis集群和主從復(fù)制嗎?因?yàn)镽edis宕機(jī)的話數(shù)據(jù)庫的數(shù)據(jù)也不能保證是最新的版本,所以得盡量保證Redis不宕機(jī)?肯定要使用redis集群模式,但可能會(huì)有主從延遲,導(dǎo)致從節(jié)點(diǎn)數(shù)據(jù)不是最新的,但關(guān)系不大??梢栽谟脩羯捎唵魏?,修改數(shù)據(jù)庫的座位和庫存,然后用戶支付后,再改數(shù)據(jù)庫的座位和庫存,每一步都做好驗(yàn)證。這樣從節(jié)點(diǎn)的數(shù)據(jù)問題會(huì)降到最低。問題4:如果在當(dāng)前的冪等驗(yàn)證邏輯中,有一個(gè)消息所對應(yīng)的冪等標(biāo)識(shí)符是不存在的,按照現(xiàn)有的邏輯是可以執(zhí)行的,但是冪等驗(yàn)證之后的業(yè)務(wù)系統(tǒng)異常了,這個(gè)時(shí)候應(yīng)該怎么處理呢(即通過了冪等的驗(yàn)證,但是后面的服務(wù)down掉了,比如說下游拋了一個(gè)異常出來)【沒太明白應(yīng)該回答什么,是指需要將冪等標(biāo)識(shí)符重新進(jìn)行設(shè)置嗎】異常了就異常了唄,把這個(gè)請求的標(biāo)識(shí)從redis中刪除了,就像分布式鎖時(shí),業(yè)務(wù)異常也要執(zhí)行解鎖一樣,讓下一個(gè)請求進(jìn)來正常執(zhí)行,然后設(shè)置好標(biāo)識(shí)位問題5:本地緩存為什么使用Caffine呢,為啥不用Guava因?yàn)閏affine的性能要遠(yuǎn)高于Guava,沒有其他復(fù)雜原因我的理解:查了下Caffine就是Guava改進(jìn)而來的,可以這么說嗎-&nbsp;Caffine在讀寫操作方面的性能更高,是基于異步的操作,將淘汰過期操作與讀寫進(jìn)行分離-&nbsp;Caffine采用了一種結(jié)合&nbsp;LRU、LFU的算法W-TinyLFU+,具有高命中率,低內(nèi)存占用的特點(diǎn)
查看5道真題和解析
點(diǎn)贊 評(píng)論 收藏
分享
評(píng)論
點(diǎn)贊
4
分享

創(chuàng)作者周榜

更多
??途W(wǎng)
??推髽I(yè)服務(wù)