qileilove

          blog已經(jīng)轉(zhuǎn)移至github,大家請訪問 http://qaseven.github.io/

          Java基礎(chǔ)加強之類加載器

           學習概述:本模塊深入講解了Java類加載方面的知識,Java類加載器和類加載機制以及類加載原理
            學習目標:掌握類加載機制和原理,能夠獨立開發(fā)自己的類加載器。
            1.類的加載
            什么是類加載? 類加載是指將類的class文件讀入內(nèi)存,并為之創(chuàng)建一個Java.lang.Class對象,也就是說當程序中使用任何類時,系統(tǒng)都會為之建立一個java.lang.Class對象。
            類加載器負責加載所有類,系統(tǒng)為所有被載入內(nèi)存中的類生成一個java.lang.Class實例。一旦一個類被載入JVM中,同一個類不會再被再次載入。
            思考問題:怎么樣才算同一個類?
            當JVM啟動時,會形成三個類加載器組成的原始類加載器層次結(jié)構(gòu):
            【BootStrap ClassLoader】根類加載器 這是一個特殊的加載器,他并不是有Java編寫,而是JVM自身實現(xiàn)的
            【Extension Classloader】擴展類加載器
            【System Classloader】系統(tǒng)類加載器
            類加載器的父子關(guān)系:
            實驗獲得類加載器以及了解類加載器的層次結(jié)構(gòu):
          public  class ClassloaderDemo{
          public static  void main(String[] args){
          System.out.printlb(ClassLoaderDemo.class.getClassLoader().getName());
          System.out.println(System.class.getClassloader());
          ClassLoader classloader = ClassLoaderDemo.class.getClassLoader());
          while(loader!=null){
          System.out.println(loader.getClass().getName());
          loader=loader.getParent();
          }
          }
            注意:程序會拋出異常,因為JVM根類加載器不是Java類。
            2.類的加載機制,如圖所示:
            <1>全盤負責:所謂全盤負責,就是說當一個類加載器負責加載某個Class的時候,該Class所依賴的和引用的其他Class也將由該類加載器負責載入,除非顯式使用另外一個                            類加載器來實現(xiàn)載入。
            <2>父類委托:意思是先讓父類加載器試圖加載該Class,只有父類加載器無法加載該類是才嘗試從自己的路徑中加載該類。
            <3>緩存機制:緩存機制將會保證所有被加載過的Class都會被緩存,當程序中需要使用某個Class時,類加載器先從緩存中搜索該Class,只有當緩存中不存在該Class對象              時,系統(tǒng)才重新讀取該類對應的二進制數(shù)據(jù)。這就是為什么我們修改Class后,JVM必須重新啟動,修改才生效的原因。
            類加載器的父子關(guān)系:用戶類加載器—>系統(tǒng)類加載器—>擴展類加載器—>根類加載器
            類加載機制:
            <1>當JVM需要加載一個類是,到底指派哪個類加載器去加載呢?
            首先當前線程的類加載器去加載線程中的第一個類,如果A類中引用了B類,JVM將使用加載A類的加載器來加載B類,最后還可以調(diào)用ClassLoader。loadeClass方法指定        某個類加載器去加載某個類。
            <2>每個類加載器在加載類時,先委托給其上級加載器。
            注意兩點:
            當所有的祖宗類加載器都沒有加載到類,回到發(fā)起類加載器,還加載不了,那么程序?qū)伋鯟lassNotFoundExcetpion,而不是去找發(fā)起類加載器的兒子,因為沒有                     getChild ()方法,即使有,那么選擇哪一個兒子加載器呢?
            面試題:能不能自己寫一個類叫Java.lang.System?
            答案:可以寫,但是因為JVM委托機制的存在,會先找到JVM根類加載器,我自己寫也可以,那么我要拋開委托加載機制,我自己指定一個ClassLoader。


           3.自定義類加載器
            JVM中除了根類加載器之外的所有類加載器都是classloader的子類實例,我們完全可以通過擴展ClassLoader的子類,并重寫ClassLoader所包含的的方法來實現(xiàn)自定義類       加載器,ClassLoader有兩個關(guān)鍵的方法:loadClass(),findClass()。
            不過我們一般推薦重寫findClass()方法,而不是loadClass()方法,因為重寫findClass()可以避免覆蓋默認類加載器的父類委托,緩存機制兩種策略。
            下面是我自己編寫的一個類加載器:
          package snippet;
          import java.io.File;
          import java.io.FileInputStream;
          import java.io.FileNotFoundException;
          import java.io.IOException;
          import java.io.InputStream;
          /**
          *
          * @author Administrator
          *自定義類加載器
          */
          public class MyClassLoader extends ClassLoader {
          // 獲取java源文件的二進制碼
          public byte[] getBytes(String filename){
          File file = new File(filename);
          InputStream ips=null;
          byte[] b = new byte[(int) file.length()];
          try {
          ips = new FileInputStream(file);
          int raw =ips.read(b);
          if(raw!=file.length()){
          throw new IOException("無法完整讀取文件");
          }
          } catch (FileNotFoundException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
          } catch (IOException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
          }
          finally{
          if(ips!=null){
          try {
          ips.close();
          } catch (IOException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
          }
          }
          }
          return b;
          }
          public boolean compile(String javaFile){
          System.out.println("正在編譯");
          Process p=null;
          try {
          //調(diào)用系統(tǒng)javac命令
          p=Runtime.getRuntime().exec("javac" + javaFile);
          try {
          p.waitFor();
          } catch (InterruptedException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
          }
          } catch (IOException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
          }
          int ret = p.exitValue();
          return ret==0;
          }
          @Override
          protected Class<?> findClass(String name) {
          Class<?> clazz=null;
          String fileStub = name.replace(".", "/");
          String javaFileName = fileStub + ".java";
          String classFileName = fileStub + ".class";
          File javaFile = new File(javaFileName);
          File classFile = new File(classFileName);
          //如果java源文件存在并且class文件不存在,或者java源文件比class文件修改的時間晚
          if(javaFile.exists()&&(!classFile.exists()||javaFile.lastModified()>classFile.lastModified())){
          if(!compile(javaFileName)||!classFile.exists()){
          try {
          throw new ClassNotFoundException("未發(fā)現(xiàn)class文件");
          } catch (ClassNotFoundException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
          }
          }
          //如果class文件已經(jīng)存在,那么直接生成字節(jié)碼
          if(classFile.exists()){
          byte[] b = getBytes(classFileName);
          clazz = defineClass(name, b, 0, b.length);
          }
          //如果為空,標明加載失敗
          if(clazz==null){
          try {
          throw new ClassNotFoundException(name);
          } catch (ClassNotFoundException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
          }
          }
          }
          return clazz;
          }
          }
            上面代碼重寫了findClass方法,通過重寫該方法就可以實現(xiàn)自定義的類加載機制。
            學習總結(jié):1.了解了JVM三種類加載器(根類加載器,系統(tǒng)類加載器,擴展類加載器),明白了三種類加載器的作用和范圍
            2.學習了JVM三種類加載機制(父類委托,緩存,全盤負責)
            3.學習了如何自定義類加載器,通過繼承ClassLoader類,特別要注意兩個關(guān)鍵方法:loadClass()和findClass()兩種方法的機制和不同。

          posted on 2013-12-24 11:50 順其自然EVO 閱讀(182) 評論(0)  編輯  收藏


          只有注冊用戶登錄后才能發(fā)表評論。


          網(wǎng)站導航:
          博客園   IT新聞   Chat2DB   C++博客   博問  
           
          <2013年12月>
          24252627282930
          1234567
          891011121314
          15161718192021
          22232425262728
          2930311234

          導航

          統(tǒng)計

          常用鏈接

          留言簿(55)

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 西乌珠穆沁旗| 根河市| 湛江市| 建瓯市| 当雄县| 霍城县| 屏山县| 红河县| 天水市| 渭源县| 九龙城区| 紫云| 云阳县| 东城区| 和政县| 五原县| 星子县| 泸西县| 涟源市| 交口县| 方城县| 靖远县| 吉木萨尔县| 金平| 托里县| 小金县| 丹凤县| 西藏| 富宁县| 西和县| 仙居县| 老河口市| 大关县| 灵川县| 宁津县| 昌乐县| 凉城县| 涡阳县| 高阳县| 靖西县| 洞头县|