乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      Java虛擬機(jī)學(xué)習(xí)(10):類加載器(ClassLoader)

       冬O_O煦 2016-11-19


      來源:java2000_wl

      鏈接:blog.csdn.net/java2000_wl/article/details/8222876


      類加載器(ClassLoader)用來加載 class字節(jié)碼到 Java 虛擬機(jī)中。一般來說,Java 虛擬機(jī)使用 Java 類的方式如下:Java 源文件在經(jīng)過 Javac之后就被轉(zhuǎn)換成 Java 字節(jié)碼文件(.class 文件)。類加載器負(fù)責(zé)讀取 Java 字節(jié)代碼,并轉(zhuǎn)換成 java.lang.Class 類的一個實例。每一個這樣的實例用來表示一個 Java 類。實際的情況可能更加復(fù)雜,比如 Java 字節(jié)代碼可能是通過工具動態(tài)生成的,也可能是通過網(wǎng)絡(luò)下載。


      類與類加載器


      類加載器雖然只用于實現(xiàn)類的加載動作,但它在Java程序中起到的作用卻遠(yuǎn)遠(yuǎn)不限于類加載階段。對于任意一個類,都需要由加載它的類加載器和這個類本身一同確立其在Java虛擬中的唯一性。說通俗一些,比較兩個類是否“相等”,只有在兩個類是由同一個類加載器的前提之下才有意義,否則,即使這兩個類來源于同一個class文件,只要加載它的類加載器不同,那這兩個類必定不相等。這里所指的“相等”包括代表類的Class對象的equal方法、isAssignableFrom()、isInstance()方法及instance關(guān)鍵字返回的結(jié)果。


      類加載器分類:



      主要分為Bootstrap ClassLoader、Extension ClassLoader、Application ClassLoader和User Defined ClassLoader。


      啟動類加載器(Bootstrap ClassLoader):


      這個類加載器使用C++語言實現(xiàn),并非ClassLoader的子類。主要負(fù)責(zé)加載存放在JAVA_HOME /  jre /  lib / rt.jar里面所有的class文件,或者被-Xbootclasspath參數(shù)所指定路徑中以rt.jar命名的文件。


      擴(kuò)展類加載器(Extension ClassLoader):


      這個加載器由sun.misc.Launcher$ExtClassLoader實現(xiàn),它負(fù)責(zé)加載AVA_HOME /  lib / ext目錄中的,或者被java.ext.dirs系統(tǒng)變量所指定的路徑中的所有類庫。


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


      這個加載器由sun.misc.Launcher$AppClassLoader實現(xiàn),它負(fù)責(zé)加載classpath對應(yīng)的jar及目錄。一般情況下這個就是程序中默認(rèn)的類加載器。


      自定義類加載器(User Defined ClassLoader):


      開發(fā)人員繼承ClassLoader抽象類自行實現(xiàn)的類加載器,基于自行開發(fā)的ClassLoader可用于并非加載classpath中(例如從網(wǎng)絡(luò)上下載的jar或二進(jìn)制字節(jié)碼)、還可以在加載class文件之前做些小動作 如:加密等。


      雙親委托模型:


      上圖中所展示的類加載器之間的這種層次關(guān)系,就稱為類加載器的雙親委托模型。雙親委托模型要求除了頂層的啟動類加載器外,其余的類加載器都應(yīng)當(dāng)有自己的父類加載器。這里類加載器之間的父子關(guān)系一般不會以繼承的關(guān)系來實現(xiàn),而是使用組合關(guān)系來復(fù)用父加載器的代碼。


      public abstract class ClassLoader {  

       

          private static native void registerNatives();  

          static {  

              registerNatives();  

          }  

       

          // The parent class loader for delegation  

          private ClassLoader parent;  

       

          // Hashtable that maps packages to certs  

          private Hashtable package2certs = new Hashtable(11);  

      }


      雙親委托的工作過程:如果一個類加載器收到了一個類加載請求,它首先不會自己去加載這個類,而是把這個請求委托給父類加載器去完成,每一個層次的類加載器都是如此,因此所有的加載請求最終都應(yīng)該傳送到頂層的啟動類加載器中,只有當(dāng)父類加載器反饋自己無法完成加載請求(它管理的范圍之中沒有這個類)時,子加載器才會嘗試著自己去加載。


      使用雙親委托模型來組織類加載器之間的關(guān)系,有一個顯而易見的好處就是Java類隨著它的類加載器一起具備了一種帶有優(yōu)先級的層次關(guān)系,例如java.lang.Object存放在rt.jar之中,無論那個類加載器要加載這個類,最終都是委托給啟動類加載器進(jìn)行加載,因此Object類在程序的各種類加載器環(huán)境中都是同一個類,相反,如果沒有雙親委托模型,由各個類加載器去完成的話,如果用戶自己寫一個名為java.lang.Object的類,并放在classpath中,應(yīng)用程序中可能會出現(xiàn)多個不同的Object類,java類型體系中最基本安全行為也就無法保證。


      類加載器SPI:


      java.lang.ClassLoader 類提供的幾個關(guān)鍵方法:


      loadClass: 此方法負(fù)責(zé)加載指定名字的類,首先會從已加載的類中去尋找,如果沒有找到;從parent ClassLoader[ExtClassLoader]中加載;如果沒有加載到,則從Bootstrap ClassLoader中嘗試加載(findBootstrapClassOrNull方法), 如果還是加載失敗,則拋出異常ClassNotFoundException, 在調(diào)用自己的findClass方法進(jìn)行加載。如果要改變類的加載順序可以覆蓋此方法;如果加載順序相同,則可以通過覆蓋findClass方法來做特殊處理,例如:解密,固定路徑尋找等。當(dāng)通過整個尋找類的過程仍然未獲取Class對象,則拋出ClassNotFoundException異常。


      如果類需要resolve,在調(diào)用resolveClass進(jìn)行鏈接。


        protected synchronized Class loadClass(String name, boolean resolve)  

      throws ClassNotFoundException  

         {  

      // First, check if the class has already been loaded  

      Class c = findLoadedClass(name);  

      if (c == null) {  

          try {  

          if (parent != null) {  

              c = parent.loadClass(name, false);  

          } else {  

              c = findBootstrapClassOrNull(name);  

          }  

          } catch (ClassNotFoundException e) {  

                     // ClassNotFoundException thrown if class not found  

                     // from the non-null parent class loader  

                 }  

                 if (c == null) {  

              // If still not found, then invoke findClass in order  

              // to find the class.  

              c = findClass(name);  

          }  

      }  

      if (resolve) {  

          resolveClass(c);  

      }  

      return c;  

         }


      findLoadedClass 此方法負(fù)責(zé)從當(dāng)前ClassLoader實例對象的緩存中尋找已加載的類,調(diào)用的為native方法。


      protected final Class findLoadedClass(String name) {  

      (!checkName(name))  

       return null;  

      urn findLoadedClass0(name);  

      }  

       

      private native final Class findLoadedClass0(String name);


      findClass 此方法直接拋出ClassNotFoundException異常,因此要通過覆蓋loadClass或此方法來以自定義的方式加載相應(yīng)的類。


      protected Class findClass(String name) throws ClassNotFoundException {  

      ow new ClassNotFoundException(name);  

      }


      findSystemClass  此方法是從sun.misc.Launcher$AppClassLoader中尋找類,如果未找到,則繼續(xù)從BootstrapClassLoader中尋找,如果仍然未找到,返回null


         protected final Class findSystemClass(String name)  

      throws ClassNotFoundException  

         {  

      ClassLoader system = getSystemClassLoader();  

      if (system == null) {  

          if (!checkName(name))  

          throw new ClassNotFoundException(name);  

                 Class cls = findBootstrapClass(name);  

                 if (cls == null) {  

                     throw new ClassNotFoundException(name);  

                 }   

          return cls;  

      }  

      return system.loadClass(name);  

         }


      defineClass 此方法負(fù)責(zé)將二進(jìn)制字節(jié)流轉(zhuǎn)換為Class對象,這個方法對于自定義類加載器而言非常重要。如果二進(jìn)制的字節(jié)碼的格式不符合jvm class文件格式規(guī)范,則拋出ClassFormatError異常;如果生成的類名和二進(jìn)制字節(jié)碼不同,則拋出NoClassDefFoundError;如果加載的class是受保護(hù)的、采用不同簽名的,或者類名是以java.開頭的,則拋出SecurityException異常。


      protected final Class defineClass(String name, byte[] b, int off, int len,  

                           ProtectionDomain protectionDomain)  

          throws ClassFormatError  

          {  

               return defineClassCond(name, b, off, len, protectionDomain, true);  

          }  

       

          // Private method w/ an extra argument for skipping class verification  

          private final Class defineClassCond(String name,  

                                                 byte[] b, int off, int len,  

                                                 ProtectionDomain protectionDomain,  

                                                 boolean verify)  

              throws ClassFormatError  

          {  

          protectionDomain = preDefineClass(name, protectionDomain);  

       

          Class c = null;  

              String source = defineClassSourceLocation(protectionDomain);  

       

          try {  

              c = defineClass1(name, b, off, len, protectionDomain, source,  

                                   verify);  

          } catch (ClassFormatError cfe) {  

              c = defineTransformedClass(name, b, off, len, protectionDomain, cfe,  

                                             source, verify);  

          }  

       

          postDefineClass(c, protectionDomain);  

          return c;  

          }


      resolveClass 此方法負(fù)責(zé)完成Class對象的鏈接,如果鏈接過,則直接返回。


      常見異常:


      ClassNotFoundException  這是最常見的異常,產(chǎn)生這個異常的原因為在當(dāng)前的ClassLoader 中加載類時,未找到類文件,


      NoClassDefFoundError  這個異常是因為  加載到的類中引用到的另外類不存在,例如要加載A,而A中盜用了B,B不存在或當(dāng)前的ClassLoader無法加載B,就會拋出這個異常。


      LinkageError 該異常在自定義ClassLoader的情況下更容易出現(xiàn),主要原因是此類已經(jīng)在ClassLoader加載過了,重復(fù)的加載會造成該異常。


      本系列:



      關(guān)注「ImportNew」

      看更多 Java 技術(shù)精選文章

      ↓↓

        本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多