自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

說(shuō)說(shuō) JVM 的類(lèi)加載機(jī)制『非專(zhuān)業(yè)』

云計(jì)算 虛擬化
類(lèi)是在運(yùn)行期間第一次使用時(shí)動(dòng)態(tài)加載的,而不是一次性加載所有類(lèi)。因?yàn)槿绻淮涡约虞d,那么會(huì)占用很多的內(nèi)存。

[[396813]]

類(lèi)加載機(jī)制

類(lèi)是在運(yùn)行期間第一次使用時(shí)動(dòng)態(tài)加載的,而不是一次性加載所有類(lèi)。因?yàn)槿绻淮涡约虞d,那么會(huì)占用很多的內(nèi)存。

類(lèi)的生命周期

包括以下 7 個(gè)階段:

  • 「加載(Loading)」
  • 「驗(yàn)證(Verification)」
  • 「準(zhǔn)備(Preparation)」
  • 「解析(Resolution)」
  • 「初始化(Initialization)」
  • 使用(Using)
  • 卸載(Unloading)

類(lèi)加載過(guò)程 --- new 一個(gè)對(duì)象的過(guò)程

包含加載、驗(yàn)證、準(zhǔn)備、解析和初始化這 5 個(gè)階段。

1.加載

加載過(guò)程完成以下三件事:

其中二進(jìn)制字節(jié)流可以從以下方式中獲?。?/p>

  • 從 ZIP 包讀取,成為 JAR、EAR、WAR 格式的基礎(chǔ)。
  • 從網(wǎng)絡(luò)中獲取,最典型的應(yīng)用是 Applet。
  • 運(yùn)行時(shí)計(jì)算生成,例如動(dòng)態(tài)代理技術(shù),在 java.lang.reflect.Proxy 使用 ProxyGenerator.generateProxyClass 的代理類(lèi)的二進(jìn)制字節(jié)流。
  • 由其他文件生成,例如由 JSP 文件生成對(duì)應(yīng)的 Class 類(lèi)。
  • 通過(guò)類(lèi)的完全限定名稱(chēng)獲取定義該類(lèi)的二進(jìn)制字節(jié)流。
  • 將該字節(jié)流表示的靜態(tài)存儲(chǔ)結(jié)構(gòu)轉(zhuǎn)換為方法區(qū)的運(yùn)行時(shí)存儲(chǔ)結(jié)構(gòu)。
  • 在內(nèi)存中生成一個(gè)代表該類(lèi)的 Class 對(duì)象,作為方法區(qū)中該類(lèi)各種數(shù)據(jù)的訪(fǎng)問(wèn)入口。

2.驗(yàn)證

格式驗(yàn)證:驗(yàn)證是否符合class文件規(guī)范 語(yǔ)義驗(yàn)證:檢查一個(gè)被標(biāo)記為final的類(lèi)型是否包含子類(lèi);檢查一個(gè)類(lèi)中的final方法是否被子類(lèi)進(jìn)行重寫(xiě);確保父類(lèi)和子類(lèi)之間沒(méi)有不兼容的一些方法聲明(比如方法簽名相同,但方法的返回值不同) 操作驗(yàn)證:在操作數(shù)棧中的數(shù)據(jù)必須進(jìn)行正確的操作,對(duì)常量池中的各種符號(hào)引用執(zhí)行驗(yàn)證(通常在解析階段執(zhí)行,檢查是否可以通過(guò)符號(hào)引用中描述的全限定名定位到指定類(lèi)型上,以及類(lèi)成員信息的訪(fǎng)問(wèn)修飾符是否允許訪(fǎng)問(wèn)等)

3.準(zhǔn)備

類(lèi)變量是被 static 修飾的變量,準(zhǔn)備階段為類(lèi)變量分配內(nèi)存并設(shè)置初始值,使用的是方法區(qū)的內(nèi)存。

  1. public static int value = 123; 

如果類(lèi)變量是常量,那么它將初始化為表達(dá)式所定義的值而不是 0。例如下面的常量 value 被初始化為 123 而不是 0。

  1. public static final int value = 123; 

實(shí)例變量不會(huì)在這階段分配內(nèi)存,它會(huì)在對(duì)象實(shí)例化時(shí)隨著對(duì)象一起被分配在堆中。

4.解析

將常量池中的符號(hào)引用轉(zhuǎn)為直接引用(得到類(lèi)或者字段、方法在內(nèi)存中的指針或者偏移量,以便直接調(diào)用該方法),這個(gè)可以在初始化之后再執(zhí)行,可以支持 Java 的動(dòng)態(tài)綁定。

以上2、3、4三個(gè)階段又合稱(chēng)為鏈接階段,鏈接階段要做的是將加載到JVM中的二進(jìn)制字節(jié)流的類(lèi)數(shù)據(jù)信息合并到JVM的運(yùn)行時(shí)狀態(tài)中。

5.初始化

初始化階段是虛擬機(jī)執(zhí)行類(lèi)構(gòu)造器 () 方法的過(guò)程,是真正開(kāi)始執(zhí)行類(lèi)中定義的 Java 程序代碼。在前面的準(zhǔn)備階段,類(lèi)變量已經(jīng)賦過(guò)一次系統(tǒng)要求的初始值,而在初始化階段,主要根據(jù)程序員通過(guò)程序制定的主觀計(jì)劃去初始化類(lèi)變量和其它資源。

() 是由編譯器自動(dòng)收集類(lèi)中所有類(lèi)變量的賦值動(dòng)作和靜態(tài)語(yǔ)句塊中的語(yǔ)句合并產(chǎn)生的,編譯器收集的順序由語(yǔ)句在源文件中出現(xiàn)的順序決定。特別注意的是,靜態(tài)語(yǔ)句塊只能訪(fǎng)問(wèn)到定義在它之前的類(lèi)變量,定義在它之后的類(lèi)變量只能賦值,不能訪(fǎng)問(wèn)。

虛擬機(jī)會(huì)保證一個(gè)類(lèi)的 () 方法在多線(xiàn)程環(huán)境下被正確的加鎖和同步,如果多個(gè)線(xiàn)程同時(shí)初始化一個(gè)類(lèi),只會(huì)有一個(gè)線(xiàn)程執(zhí)行這個(gè)類(lèi)的\ () 方法,其它線(xiàn)程都會(huì)阻塞等待,直到活動(dòng)線(xiàn)程執(zhí)行\(zhòng) () 方法完畢。如果在一個(gè)類(lèi)的 () 方法中有耗時(shí)的操作,就可能造成多個(gè)線(xiàn)程阻塞,在實(shí)際過(guò)程中此種阻塞很隱蔽。

上述步驟簡(jiǎn)單來(lái)說(shuō)就是分為以下兩步:

  • 類(lèi)變量的賦值操作
  • 執(zhí)行static代碼塊。static代碼塊只有jvm能夠調(diào)用。如果是多線(xiàn)程需要同時(shí)初始化一個(gè)類(lèi),僅僅只能允許其中一個(gè)線(xiàn)程對(duì)其執(zhí)行初始化操作,其余線(xiàn)程必須等待,只有在活動(dòng)線(xiàn)程執(zhí)行完對(duì)類(lèi)的初始化操作之后,才會(huì)通知正在等待的其他線(xiàn)程。

最終,方法區(qū)會(huì)存儲(chǔ)當(dāng)前類(lèi)的類(lèi)信息,包括類(lèi)的靜態(tài)變量、類(lèi)初始化代碼(定義靜態(tài)變量時(shí)的賦值語(yǔ)句和靜態(tài)初始化代碼塊)、實(shí)例變量定義、實(shí)例初始化代碼(定義實(shí)例變量時(shí)的賦值語(yǔ)句實(shí)例代碼塊和構(gòu)造方法)和實(shí)例方法,還有父類(lèi)的類(lèi)信息引用。

創(chuàng)建對(duì)象

假設(shè)是第一次使用一個(gè)類(lèi)的話(huà),那么需要經(jīng)過(guò)上述的類(lèi)加載的過(guò)程,之后才是創(chuàng)建對(duì)象。

「1、在堆區(qū)分配對(duì)象需要的內(nèi)存」

分配的內(nèi)存包括本類(lèi)和父類(lèi)的所有實(shí)例變量,但不包括任何靜態(tài)變量

「2、對(duì)所有實(shí)例變量賦默認(rèn)值」

將方法區(qū)內(nèi)對(duì)實(shí)例變量的定義拷貝一份到堆區(qū),然后賦默認(rèn)值

「3、執(zhí)行實(shí)例初始化代碼」

初始化順序是先初始化父類(lèi)再初始化子類(lèi),初始化時(shí)先執(zhí)行實(shí)例代碼塊然后是構(gòu)造方法。(第一執(zhí)行類(lèi)中的靜態(tài)代碼,包括靜態(tài)成 員變量的初始化和靜態(tài)語(yǔ)句塊的執(zhí)行;第二執(zhí)行類(lèi)中的非靜態(tài)代碼,包括非靜態(tài)成員變量的初始化和非靜態(tài)語(yǔ)句塊的執(zhí)行,最后執(zhí) 行構(gòu)造函數(shù)。在繼承的情況下,會(huì)首先執(zhí)行父類(lèi)的靜態(tài)代碼,然后執(zhí)行子類(lèi)的靜態(tài)代碼;之后執(zhí)行父類(lèi)的非靜態(tài)代碼和構(gòu)造函數(shù); 最后執(zhí)行子類(lèi)的非靜態(tài)代碼和構(gòu)造函數(shù))

「4、如果有類(lèi)似于Child c = new Child()形式的c引用的話(huà),在棧區(qū)定義Child類(lèi)型引用變量c,然后將堆區(qū)對(duì)象的地址賦值給它」

需要注意的是,「每個(gè)子類(lèi)對(duì)象持有父類(lèi)對(duì)象的引用」,可在內(nèi)部通過(guò)super關(guān)鍵字來(lái)調(diào)用父類(lèi)對(duì)象,但在外部不可訪(fǎng)問(wèn)。

存在繼承的情況下,初始化順序?yàn)椋?/p>

  • 父類(lèi)(靜態(tài)變量、靜態(tài)語(yǔ)句塊)
  • 子類(lèi)(靜態(tài)變量、靜態(tài)語(yǔ)句塊)
  • 父類(lèi)(實(shí)例變量、普通語(yǔ)句塊)
  • 父類(lèi)(構(gòu)造函數(shù))
  • 子類(lèi)(實(shí)例變量、普通語(yǔ)句塊)
  • 子類(lèi)(構(gòu)造函數(shù))

類(lèi)初始化的情況

主動(dòng)引用

虛擬機(jī)規(guī)范中并沒(méi)有強(qiáng)制約束何時(shí)進(jìn)行加載,但是規(guī)范嚴(yán)格規(guī)定了有且只有下列五種情況必須對(duì)類(lèi)進(jìn)行初始化(加載、驗(yàn)證、準(zhǔn)備都會(huì)隨之發(fā)生):

  • 遇到 new、getstatic、putstatic、invokestatic 這四條字節(jié)碼指令時(shí),如果類(lèi)沒(méi)有進(jìn)行過(guò)初始化,則必須先觸發(fā)其初始化。最常見(jiàn)的生成這 4 條指令的場(chǎng)景是:使用 new 關(guān)鍵字實(shí)例化對(duì)象的時(shí)候;讀取或設(shè)置一個(gè)類(lèi)的靜態(tài)字段(被 final 修飾、已在編譯期把結(jié)果放入常量池的靜態(tài)字段除外)的時(shí)候;以及調(diào)用一個(gè)類(lèi)的靜態(tài)方法的時(shí)候。
  • 使用 java.lang.reflect 包的方法對(duì)類(lèi)進(jìn)行反射調(diào)用的時(shí)候,如果類(lèi)沒(méi)有進(jìn)行初始化,則需要先觸發(fā)其初始化。
  • 當(dāng)初始化一個(gè)類(lèi)的時(shí)候,如果發(fā)現(xiàn)其父類(lèi)還沒(méi)有進(jìn)行過(guò)初始化,則需要先觸發(fā)其父類(lèi)的初始化。
  • 當(dāng)虛擬機(jī)啟動(dòng)時(shí),用戶(hù)需要指定一個(gè)要執(zhí)行的主類(lèi)(包含 main() 方法的那個(gè)類(lèi)),虛擬機(jī)會(huì)先初始化這個(gè)主類(lèi)。

被動(dòng)引用

以上的行為稱(chēng)為對(duì)一個(gè)類(lèi)進(jìn)行主動(dòng)引用。除此之外,所有引用類(lèi)的方式都不會(huì)觸發(fā)初始化,稱(chēng)為被動(dòng)引用。被動(dòng)引用的常見(jiàn)例子包括:

  • 通過(guò)子類(lèi)引用父類(lèi)的靜態(tài)字段,不會(huì)導(dǎo)致子類(lèi)初始化。
  1. System.out.println(SubClass.value); // value 字段在 SuperClass 中定義 

通過(guò)數(shù)組定義來(lái)引用類(lèi),不會(huì)觸發(fā)此類(lèi)的初始化。該過(guò)程會(huì)對(duì)數(shù)組類(lèi)進(jìn)行初始化,數(shù)組類(lèi)是一個(gè)由虛擬機(jī)自動(dòng)生成的、直接繼承自 Object 的子類(lèi),其中包含了數(shù)組的屬性和方法。

  1. SuperClass[] sca = new SuperClass[10]; 
  • 常量在編譯階段會(huì)存入調(diào)用類(lèi)的常量池中,本質(zhì)上并沒(méi)有直接引用到定義常量的類(lèi),因此不會(huì)觸發(fā)定義常量的類(lèi)的初始化。
  1. System.out.println(ConstClass.HELLOWORLD); 

類(lèi)與類(lèi)加載器

兩個(gè)類(lèi)相等,需要類(lèi)本身相等,并且使用同一個(gè)類(lèi)加載器進(jìn)行加載。這是因?yàn)槊恳粋€(gè)類(lèi)加載器都擁有一個(gè)獨(dú)立的類(lèi)名稱(chēng)空間。那么最終的相等包括了類(lèi)的 Class 對(duì)象的 equals() 方法、isAssignableFrom() 方法、isInstance() 方法的返回結(jié)果為 true,也包括使用 instanceof 關(guān)鍵字做對(duì)象所屬關(guān)系判定結(jié)果為 true。

從 Java 虛擬機(jī)的角度來(lái)講,只存在以下兩種不同的類(lèi)加載器:

  • 啟動(dòng)類(lèi)加載器(Bootstrap ClassLoader),使用 C++ 實(shí)現(xiàn),是虛擬機(jī)自身的一部分;
  • 所有其它類(lèi)的加載器,使用 Java 實(shí)現(xiàn),獨(dú)立于虛擬機(jī),繼承自抽象類(lèi) java.lang.ClassLoader。

那么上述又可以分為以下三種類(lèi)加載器:BootstrapClassLoader、ExtensionClassLoader、App ClassLoader

  • 啟動(dòng)類(lèi)加載器(BootstrapClassLoader)是嵌在JVM內(nèi)核中的加載器,該加載器是用C++語(yǔ)言寫(xiě)的,主要負(fù)載加載JAVA_HOME/lib下的類(lèi)庫(kù),或者被 -Xbootclasspath 參數(shù)所指定的路徑中的,并且是虛擬機(jī)識(shí)別的(僅按照文件名識(shí)別,如 rt.jar,名字不符合的類(lèi)庫(kù)即使放在 lib 目錄中也不會(huì)被加載)。

啟動(dòng)類(lèi)加載器無(wú)法被 Java 程序直接引用,用戶(hù)在編寫(xiě)自定義類(lèi)加載器時(shí),如果需要把加載請(qǐng)求委派給啟動(dòng)類(lèi)加載器,直接使用 null 代替即可。

  • 擴(kuò)展類(lèi)加載器(ExtensionClassLoader)是用JAVA編寫(xiě),由 ExtClassLoader(sun.misc.Launcher$ExtClassLoader)實(shí)現(xiàn)的。它負(fù)責(zé)將 /lib/ext 或者被 java.ext.dir 系統(tǒng)變量所指定路徑中的所有類(lèi)庫(kù)加載到內(nèi)存中,開(kāi)發(fā)者可以直接使用擴(kuò)展類(lèi)加載器。

它的父類(lèi)加載器是Bootstrap。

  • 應(yīng)用程序類(lèi)加載器(Application ClassLoader)這個(gè)類(lèi)加載器是由 AppClassLoader(sun.misc.Launcher$AppClassLoader)實(shí)現(xiàn)的。一般負(fù)責(zé)加載應(yīng)用程序classpath目錄下的所有jar和class文件。

開(kāi)發(fā)者可以直接使用這個(gè)類(lèi)加載器,如果應(yīng)用程序中沒(méi)有自定義過(guò)自己的類(lèi)加載器,一般情況下這個(gè)就是程序中默認(rèn)的類(lèi)加載器。

它的父加載器為ExteClassLoader。

雙親委派模型

應(yīng)用程序是由三種類(lèi)加載器互相配合從而實(shí)現(xiàn)類(lèi)加載,除此之外還可以加入自己定義的類(lèi)加載器。下圖展示了類(lèi)加載器之間的層次關(guān)系,稱(chēng)為雙親委派模型(Parents Delegation Model)。這里的父子關(guān)系一般通過(guò)委托來(lái)實(shí)現(xiàn),而不是繼承關(guān)系(Inheritance)。

  • 工作流程

如果一個(gè)類(lèi)加載器收到了一個(gè)類(lèi)加載請(qǐng)求,它不會(huì)自己去嘗試加載這個(gè)類(lèi),而是把這個(gè)請(qǐng)求轉(zhuǎn)交給父類(lèi)加載器去完成。每一個(gè)層次的類(lèi)加載器都是如此。因此所有的類(lèi)加載請(qǐng)求都應(yīng)該傳遞到最頂層的啟動(dòng)類(lèi)加載器中,只有到父類(lèi)加載器反饋?zhàn)约簾o(wú)法完成這個(gè)加載請(qǐng)求(在它的搜索范圍沒(méi)有找到這個(gè)類(lèi))時(shí),子類(lèi)加載器才會(huì)嘗試自己去加載。

  • 好處

使得 Java 類(lèi)隨著它的類(lèi)加載器一起具有一種帶有優(yōu)先級(jí)的層次關(guān)系,從而使得基礎(chǔ)類(lèi)得到統(tǒng)一。

例如 java.lang.Object 存放在 rt.jar 中,如果編寫(xiě)另外一個(gè) java.lang.Object 并放到 ClassPath 中,程序可以編譯通過(guò)。由于雙親委派模型的存在,所以在 rt.jar 中的 Object 比在 ClassPath 中的 Object 優(yōu)先級(jí)更高,這是因?yàn)? rt.jar 中的 Object 使用的是啟動(dòng)類(lèi)加載器,而 ClassPath 中的 Object 使用的是應(yīng)用程序類(lèi)加載器。rt.jar 中的 Object 優(yōu)先級(jí)更高,那么程序中所有的 Object 都是這個(gè) Object。

  • demo

以下是抽象類(lèi) java.lang.ClassLoader 的代碼片段,其中的 loadClass() 方法運(yùn)行過(guò)程如下:先檢查類(lèi)是否已經(jīng)加載過(guò),如果沒(méi)有則讓父類(lèi)加載器去加載。當(dāng)父類(lèi)加載器加載失敗時(shí)拋出 ClassNotFoundException,此時(shí)嘗試自己去加載。

  1. public abstract class ClassLoader { 
  2.     // The parent class loader for delegation 
  3.     private final ClassLoader parent; 
  4.  
  5.     public Class<?> loadClass(String name) throws ClassNotFoundException { 
  6.         return loadClass(namefalse); 
  7.     } 
  8.  
  9.     protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { 
  10.         synchronized (getClassLoadingLock(name)) { 
  11.             // Firstcheck if the class has already been loaded 
  12.             Class<?> c = findLoadedClass(name); 
  13.             if (c == null) { 
  14.                 try { 
  15.                     if (parent != null) { 
  16.                         c = parent.loadClass(namefalse); 
  17.                     } else { 
  18.                         c = findBootstrapClassOrNull(name); 
  19.                     } 
  20.                 } catch (ClassNotFoundException e) { 
  21.                     // ClassNotFoundException thrown if class not found 
  22.                     // from the non-null parent class loader 
  23.                 } 
  24.  
  25.                 if (c == null) { 
  26.                     // If still not found, then invoke findClass in order 
  27.                     // to find the class. 
  28.                     c = findClass(name); 
  29.                 } 
  30.             } 
  31.             if (resolve) { 
  32.                 resolveClass(c); 
  33.             } 
  34.             return c; 
  35.         } 
  36.     } 
  37.  
  38.     protected Class<?> findClass(String name) throws ClassNotFoundException { 
  39.         throw new ClassNotFoundException(name); 
  40.     } 
  • 自定義類(lèi)加載器實(shí)現(xiàn)

以下代碼中的 FileSystemClassLoader 是自定義類(lèi)加載器,繼承自 java.lang.ClassLoader,用于加載文件系統(tǒng)上的類(lèi)。它首先根據(jù)類(lèi)的全名在文件系統(tǒng)上查找類(lèi)的字節(jié)代碼文件(.class 文件),然后讀取該文件內(nèi)容,最后通過(guò) defineClass() 方法來(lái)把這些字節(jié)代碼轉(zhuǎn)換成 java.lang.Class 類(lèi)的實(shí)例。

java.lang.ClassLoader 的 loadClass() 實(shí)現(xiàn)了雙親委派模型的邏輯,自定義類(lèi)加載器一般不去重寫(xiě)它,但是需要重寫(xiě) findClass() 方法。

  1. public class FileSystemClassLoader extends ClassLoader { 
  2.  
  3.     private String rootDir; 
  4.  
  5.     public FileSystemClassLoader(String rootDir) { 
  6.         this.rootDir = rootDir; 
  7.     } 
  8.  
  9.     protected Class<?> findClass(String name) throws ClassNotFoundException { 
  10.         byte[] classData = getClassData(name); 
  11.         if (classData == null) { 
  12.             throw new ClassNotFoundException(); 
  13.         } else { 
  14.             return defineClass(name, classData, 0, classData.length); 
  15.         } 
  16.     } 
  17.  
  18.     private byte[] getClassData(String className) { 
  19.         String path = classNameToPath(className); 
  20.         try { 
  21.             InputStream ins = new FileInputStream(path); 
  22.             ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
  23.             int bufferSize = 4096; 
  24.             byte[] buffer = new byte[bufferSize]; 
  25.             int bytesNumRead; 
  26.             while ((bytesNumRead = ins.read(buffer)) != -1) { 
  27.                 baos.write(buffer, 0, bytesNumRead); 
  28.             } 
  29.             return baos.toByteArray(); 
  30.         } catch (IOException e) { 
  31.             e.printStackTrace(); 
  32.         } 
  33.         return null
  34.     } 
  35.  
  36.     private String classNameToPath(String className) { 
  37.         return rootDir + File.separatorChar 
  38.                 + className.replace('.', File.separatorChar) + ".class"
  39.     } 

巨人的肩膀

程序鍋春招筆記的摘記

https://github.com/CyC2018/CS-Notes

本文轉(zhuǎn)載自微信公眾號(hào)「多選參數(shù)」,可以通過(guò)以下二維碼關(guān)注。轉(zhuǎn)載本文請(qǐng)聯(lián)系多選參數(shù)公眾號(hào)。

 

責(zé)任編輯:武曉燕 來(lái)源: 多選參數(shù)
相關(guān)推薦

2021-05-12 20:37:56

JVM 內(nèi)存管理

2023-10-31 16:00:51

類(lèi)加載機(jī)制Java

2017-09-20 08:07:32

java加載機(jī)制

2017-03-08 10:30:43

JVMJava加載機(jī)制

2023-08-02 08:38:27

JVM加載機(jī)制

2024-12-02 09:01:23

Java虛擬機(jī)內(nèi)存

2024-03-12 07:44:53

JVM雙親委托機(jī)制類(lèi)加載器

2022-10-08 08:34:34

JVM加載機(jī)制代碼

2020-05-20 22:13:26

JVM加載機(jī)制虛擬機(jī)

2021-09-24 08:10:40

Java 語(yǔ)言 Java 基礎(chǔ)

2020-10-26 11:20:04

jvm類(lèi)加載Java

2019-12-30 11:25:06

Jvm運(yùn)行java

2024-03-08 08:26:25

類(lèi)的加載Class文件Java

2021-01-06 09:01:05

類(lèi)javaclass

2021-06-16 00:57:16

JVM加載機(jī)制

2024-09-06 09:37:45

WebApp類(lèi)加載器Web 應(yīng)用

2024-02-20 08:13:35

類(lèi)加載引用Class

2021-07-05 06:51:43

Java機(jī)制類(lèi)加載器

2024-12-04 09:01:55

引導(dǎo)類(lèi)加載器C++

2021-02-28 11:58:33

JVM機(jī)制語(yǔ)言
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)