類的生命周期

      網友投稿 851 2025-04-04

      類的生命周期


      當java源代碼文件被javac編譯成class文件后,并不能直接運行, 而是需要經過加載,連接和初始化這幾個階段后才能使用。 在使用完類或JVM被銷毀后,JVM會將類卸載掉。

      類加載過程需要經過3個階段:

      加載

      連接

      初始化

      其中連接又可分為3個階段: 驗證 , 準備 , 解析。

      在加載階段,類加載器將類的class文件的二進制數據讀取到內存, 并保存到方法區,并在堆區生成該類的Class對象。

      通常有多種方式可以獲取類的二進制數據:

      通過javac編譯器編譯java源文件,讀取在本地磁盤上生成的class文件。

      從Jar,ZIP等歸檔文件中讀取class文件。

      通過網絡讀取類的字節流。

      通過動態生成字節碼的技術(如使用動態代理,cglib)來生成class。

      類的生命周期

      PS:數組由數組元素的類型的類加載器在java程序運行時加載,這是ClassLoader類的部分注釋:

      見:?測試

      1.驗證?驗證階段是為了確保類的字節流符合虛擬機規范,并且不會對虛擬機造成惡意損害。?JVM會對字節流進行如下驗證:

      文件格式驗證:會驗證class文件是否符合虛擬機規范,如是否以0×CAFEBABE開頭, 主次版本號是否在虛擬機規定范圍類,常量池中的類型是否有JVM不支持的類型。

      元數據驗證: 會對類的元信息進行語義分析,確保符合Java語法規范。

      字節碼驗證: 通過分析數據流和控制流,確保類的方法體的程序語義是合法的, 符合邏輯的。

      符號引用驗證: 確保常量池中的符號引用能在解析階段正常解析。

      2.準備: 準備階段會為類的靜態變量初始化零值,如(0,0L,null,false).

      3.解析: 解析階段會將常量池中的符號引用轉為直接引用。 符號引用包括類的全限定名,方法名的描述符,字段名的描述符。直接引用可以簡單理解為目標的內存地址。

      初始化階段是類加載過程的最后一個階段。

      在這個階段,只有主動使用類才會初始化類,總共有8種情況會涉及到主動使用類。

      當jvm執行new指令時會初始化類,即當程序創建一個類的實例對象。

      當jvm執行getstatic指令時會初始化類,即程序訪問類的靜態變量(不是靜態常量,常量歸屬于運行時常量池)。

      當jvm執行putstatic指令時會初始化類,即程序給類的靜態變量賦值。

      當jvm執行invokestatic指令時會初始化類,即程序調用類的靜態方法。

      當使用反射主動訪問這個類時,也會初始化類,如Class.forname("..."),newInstance()等等。

      當初始化一個子類的時候,會先初始化這個子類的所有父類,然后才會初始化這個子類。

      當一個類是啟動類時,即這個類擁有main方法,那么jvm會首先初始化這個類。

      MethodHandle和VarHandle可以看作是輕量級的反射調用機制,而要想使用這2個調用, 就必須先使用findStatic/findStaticVarHandle來初始化要調用的類。

      PS:見:測試

      在類被初始化完成后,就可以使用類了。

      類被卸載(Class對象被GC掉)需要滿足3個條件:

      該類的實例對象都已被GC,也就是說堆中不存在該類的實例對象。

      該類沒有在其它任何地方被使用。

      加載該類的類加載器實例已被GC。

      在JVM的生命周期中,被JVM自帶的類加載器所加載的類是不會被卸載的。 而被我們自定義的類加載器所加載的類是可能會被卸載的。

      其實只要想通一點就好了,jdk自帶的BootstrapClassLoader, PlatformClassLoader和AppClassLoader負責加載jdk提供的類, 它們(類加載器)的實例肯定不會被回收,其中BootstrapClassLoader在java中更是不能被獲取到。 而我們自定義的類加載器的實例是可以被GC掉的, 所以被我們自定義類加載器加載的類是可以被GC掉的。

      PS:使用-XX:+TraceClassUnloading 或 -Xlog:class+unload=info可以打印類卸載的信息。

      BootstrapClassLoader(用于加載Java基礎核心類庫。由c/c++編寫,Java獲取不到)。

      PlatformClassLoader (jdk9之后才有此類加載器,jdk8之前是擴展加載器ExtensionClassLoader 。PlatformClassLoader加載平臺相關的模塊,ExtensionClassLoader加載jdk擴展的模塊)。

      AppClassLoader。(應用程序類加載器,負責加載我們程序的classpath下的jar和類)。

      自定義類加載器。

      每個類加載器實例都有自己的命名空間,命名空間由該加載器及其所有父加載器加載的所有的類組成。

      在同一個命名空間中(一個類加載器實例),不會出現全限定名(包括包名)相同的2個類(不會加載2個相同名稱的類)。

      在不同的命名空間中(多個類加載器實例),可能會出現全限定名(包括包名)相同的2個類(可能加載2個相同名稱的類)。

      PS:見:測試

      雙親委派機制是為了防止類被重復加載,避免核心API遭到惡意破壞。?如Object類,它由BootstrapClassLoader在JVM啟動時加載。 如果沒有雙親委派機制,那么Object類就可以被重寫,其帶來的后果將無法想象。

      每個類都有其對應的類加載器。

      雙親委派機制是指在加載一個類的時候,JVM會判斷這個類是否已經被其類加載器加載過了。 如果已經加載過了,那么直接返回這個類。?如果沒有加載,就使用這個類對應的加載器的父類加載器判斷, 一層一層的往上判斷,最終會由BootstrapClassLoader判斷。?如果BootstrapClassLoader判斷都沒有加載這個類,?那么就由BootstrapClassLoader嘗試加載。 如果BootstrapClassLoader加載失敗了, 就由BootstrapClassLoader的子類加載器們加載。

      在jdk9之后,由于模塊化的到來,雙親委派機制也變化了一點: 如果類沒有被加載,那么會根據類名找到這個類的模塊。 如果找到了這個類的模塊, 就由這個類的模塊加載,否則仍然使用父類加載器加載。

      可以看出:在加載一個類時,是由下自上判斷類是否被加載的。如果類沒有被加載, 就由上自下嘗試加載類。

      Java JVM

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

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

      上一篇:在PPT中插入excel表格鏈接的方法步驟(ppt里怎么插excel表格鏈接)
      下一篇:word2007制作表格的兩種方法
      相關文章
      中文字幕 亚洲 有码 在线| 久久精品国产亚洲| 亚洲欧洲日产国码av系列天堂 | 亚洲人成网站免费播放| 亚洲短视频在线观看| 亚洲一区中文字幕久久| 亚洲韩国—中文字幕| 亚洲自偷自偷图片| 亚洲精品成人网站在线观看| 亚洲国产另类久久久精品小说| 亚洲精品自产拍在线观看| 亚洲精品乱码久久久久久按摩| 国产亚洲色婷婷久久99精品| 亚洲国产精品VA在线看黑人| 亚洲精品无码AV人在线播放| 国产av天堂亚洲国产av天堂| 亚洲va久久久噜噜噜久久狠狠| 无码专区—VA亚洲V天堂| 亚洲人成在线影院| 亚洲理论片在线中文字幕| 亚洲一级黄色大片| 亚洲色偷偷色噜噜狠狠99| 亚洲国产精品成人午夜在线观看| 国产亚洲一卡2卡3卡4卡新区| 国产成人亚洲综合无| 亚洲人成无码网WWW| 亚洲中文字幕无码久久精品1 | 伊人久久亚洲综合影院首页| 亚洲乱妇熟女爽到高潮的片| 国产成人亚洲午夜电影| 区三区激情福利综合中文字幕在线一区亚洲视频1| 亚洲国产日韩在线观频| 国产亚洲色婷婷久久99精品91| 日韩亚洲一区二区三区| 久久久亚洲欧洲日产国码二区 | 亚洲乱码卡三乱码新区| 亚洲欧美日韩一区二区三区| 亚洲精品国产精品乱码不卡| 亚洲av永久无码精品网站| 亚洲黄色免费网址| 最新亚洲精品国偷自产在线 |