• <tfoot id="ukgsw"><input id="ukgsw"></input></tfoot>
    
    • 久久精品精选,精品九九视频,www久久只有这里有精品,亚洲熟女乱色综合一区
      分享

      全面解析Java類加載器

       liang1234_ 2019-04-16

      深入理解和探究Java類加載機制----

      1.java.lang.ClassLoader類介紹

      java.lang.ClassLoader類的基本職責就是根據一個指定的類的名稱,找到或者生成其對應的字節代碼,然后從這些字節代碼中定義出一個Java 類,即 java.lang.Class類的一個實例。

      ClassLoader提供了一系列的方法,比較重要的方法如:

       

       

      2.JVM中類加載器的樹狀層次結構

      Java 中的類加載器大致可以分成兩類,一類是系統提供的,另外一類則是由 Java 應用開發人員編寫的。 

      引導類加載器(bootstrap class loader):

      它用來加載 Java 的核心庫(jre/lib/rt.jar),是用原生C++代碼來實現的,并不繼承自java.lang.ClassLoader。

      加載擴展類和應用程序類加載器,并指定他們的父類加載器,在java中獲取不到。 

      擴展類加載器(extensions class loader):

      它用來加載 Java 的擴展庫(jre/ext/*.jar)。Java 虛擬機的實現會提供一個擴展庫目錄。該類加載器在此目錄里面查找并加載 Java 類。 

      系統類加載器(system class loader):

      它根據 Java 應用的類路徑(CLASSPATH)來加載 Java 類。一般來說,Java 應用的類都是由它來完成加載的。可以通過 ClassLoader.getSystemClassLoader()來獲取它。

      自定義類加載器(custom class loader):

      除了系統提供的類加載器以外,開發人員可以通過繼承 java.lang.ClassLoader類的方式實現自己的類加載器,以滿足一些特殊的需求。

       

      以下測試代碼可以證明此層次結構:

      復制代碼
      public class testClassLoader {
          @Test
          public void test(){
              //application class loader
              System.out.println(ClassLoader.getSystemClassLoader());
              //extensions class loader
              System.out.println(ClassLoader.getSystemClassLoader().getParent());
              //bootstrap class loader
              System.out.println(ClassLoader.getSystemClassLoader().getParent().getParent());
          }
      }
      復制代碼

      輸出為:

       

      可以看出ClassLoader類是由AppClassLoader加載的。他的父親是ExtClassLoader,ExtClassLoader的父親無法獲取是因為它是用C++實現的。

       

      3.雙親委派機制

        某個特定的類加載器在接到加載類的請求時,首先將加載任務委托交給父類加載器,父類加載器又將加載任務向上委托,直到最父類加載器,如果最父類加載器可以完成類加載任務,就成功返回,如果不行就向下傳遞委托任務,由其子類加載器進行加載。

      雙親委派機制的好處:

        保證java核心庫的安全性(例如:如果用戶自己寫了一個java.lang.String類就會因為雙親委派機制不能被加載,不會破壞原生的String類的加載)

      代理模式

        與雙親委派機制相反,代理模式是先自己嘗試加載,如果無法加載則向上傳遞。tomcat就是代理模式。

       

      4.自定義類加載器

      復制代碼
      public class MyClassLoader extends ClassLoader{
      
          private String rootPath;
          
          public MyClassLoader(String rootPath){
              this.rootPath = rootPath;
          }
          
          @Override
          protected Class<?> findClass(String name) throws ClassNotFoundException {
              //check if the class have been loaded
              Class<?> c = findLoadedClass(name);        
              if(c!=null){
                  return c;
              }
              //load the class
              byte[] classData = getClassData(name);
              if(classData==null){
                  throw new ClassNotFoundException();
              }
              else{
                  c = defineClass(name,classData, 0, classData.length);
                  return c;
              }    
          }
          
          private byte[] getClassData(String className){
              String path = rootPath+"/"+className.replace('.', '/')+".class";
              
              InputStream is = null;
              ByteArrayOutputStream bos = null;
              try {
                  is = new FileInputStream(path);
                  bos = new ByteArrayOutputStream();
                  byte[] buffer = new byte[1024];
                  int temp = 0;
                  while((temp = is.read(buffer))!=-1){
                      bos.write(buffer,0,temp);
                  }
                  return bos.toByteArray();
              } catch (Exception e) {
                  e.printStackTrace();
              }finally{
                  try {
                      is.close();
                      bos.close();
                  } catch (Exception e) {
                      e.printStackTrace();
                  }            
              }
              
              return null;        
          }    
      
      }
      復制代碼

      測試自定義的類加載器

      創建一個測試類HelloWorld

      package testOthers;
      
      public class HelloWorld {
      
      }

      在D盤根目錄創建一個testOthers文件夾,編譯HelloWorld.java,將得到的class文件放到testOthers文件夾下。

      利用如下代碼進行測試

      復制代碼
      public class testMyClassLoader {
          @Test
          public void test() throws Exception{
              MyClassLoader loader = new MyClassLoader("D:");
              Class<?> c = loader.loadClass("testOthers.HelloWorld");
              System.out.println(c.getClassLoader());
          }
      }
      復制代碼

      輸出:

       

      說明HelloWorld類是被我們的自定義類加載器MyClassLoader加載的

       

      5.類加載過程詳解

      JVM將類加載過程分為三個步驟:裝載(Load),鏈接(Link)和初始化(Initialize)

      1) 裝載

        查找并加載類的二進制數據;

      2)鏈接

        驗證:確保被加載類信息符合JVM規范、沒有安全方面的問題。

        準備:為類的靜態變量分配內存,并將其初始化為默認值。

        解析:把虛擬機常量池中的符號引用轉換為直接引用。

      3)初始化

        為類的靜態變量賦予正確的初始值。

      ps:解析部分需要說明一下,Java 中,虛擬機會為每個加載的類維護一個常量池【不同于字符串常量池,這個常量池只是該類的字面值(例如類名、方法名)和符號引用的有序集合。 而字符串常量池,是整個JVM共享的】這些符號(如int a = 5;中的a)就是符號引用,而解析過程就是把它轉換成指向堆中的對象地址的相對地址。

       

      類的初始化步驟:

      1)如果這個類還沒有被加載和鏈接,那先進行加載和鏈接

      2)假如這個類存在直接父類,并且這個類還沒有被初始化(注意:在一個類加載器中,類只能初始化一次),那就初始化直接的父類(不適用于接口)

      3)如果類中存在static標識的塊,那就依次執行這些初始化語句。

       

       

       

        本站是提供個人知識管理的網絡存儲空間,所有內容均由用戶發布,不代表本站觀點。請注意甄別內容中的聯系方式、誘導購買等信息,謹防詐騙。如發現有害或侵權內容,請點擊一鍵舉報。
        轉藏 分享 獻花(0

        0條評論

        發表

        請遵守用戶 評論公約

        類似文章 更多

        主站蜘蛛池模板: 亚洲岛国成人免费av| 四虎成人在线观看免费| 少妇xxxxx性开放| 亚洲精品无码久久千人斩| 亚洲最大成人网色| 国产办公室秘书无码精品99| 免费观看欧美猛交视频黑人| 欧美乱妇高清无乱码免费| 2021亚洲国产精品无码| 国产综合视频一区二区三区| 在线a亚洲老鸭窝天堂| 丁香婷婷激情俺也去俺来也| 宝贝腿开大点我添添公视频免| 亚洲精品无码久久一线| 无码专区视频精品老司机| 日本一区二区三区免费播放视频站| 黑巨茎大战俄罗斯美女| 欧美高清狂热视频60一70| 免费无码VA一区二区三区| 国产午夜精品理论大片| 亚洲欧美日韩精品久久| 亚洲人成网线在线播放VA| 亚洲国产成人久久久网站| 免费人成视频网站在线18| 国产精品无码免费播放| 青青草国产线观看| 国产一区二区不卡自拍| 丝袜美腿一区二区三区| 亚洲V天堂V手机在线| 免费看国产美女裸体视频| 97无码人妻福利免费公开在线视频| 日韩中文字幕人妻一区| 无码人妻精品一区二区三区久久久| 极品粉嫩国产18尤物在线观看 | 亚洲欧美综合精品二区| 久久人人爽人人人人片AV| 国产无套护士在线观看| XXXXXHD亚洲日本HD| 国产精品久久久久7777| AV免费播放一区二区三区| 亚洲欧美综合在线天堂|