Java類加載器

          1,什么是類加載器?
                  加載類的工具.
          2,類加載器有什么作用?
                  當(dāng)程序需要的某個(gè)類,那么需要通過類加載器把類的二進(jìn)制加載到內(nèi)存中.
          類加載器也是Java類
          3,類加載器之間的父子關(guān)系和管轄范圍.



                  ClassLoader classLoader = ClassLoaderTest.class.getClassLoader();
                  while (classLoader != null) {
                      System.out.println(classLoader.getClass().getName());
                      classLoader = classLoader.getParent();
                  }
                  System.out.println(classLoader);




          4,類加載器的委托機(jī)制:
                  1>當(dāng)Java虛擬機(jī)要加載一個(gè)類時(shí),到底派出哪個(gè)類加載器去加載呢?
                              ①首先當(dāng)前線程的類加載器去加載線程中的第一個(gè)類.
                              ②如果類A中引用了類B,Java虛擬機(jī)將使用加載類A的類加載器加載類B
                              ③還可以直接調(diào)用ClassLoader.loadClass()方法來指定某個(gè)類加載器去加載某個(gè)類.
                   2>每個(gè)類加載器加載類時(shí),又先委托給其上級(jí)類加載器.
                              ①當(dāng)所有祖宗類加載器沒有加載到類
          ,回到發(fā)起者類加載器,如果還加載不了,則拋出ClassNotFoundException異常,它不會(huì) 去找發(fā)起者類加載器的兒子,因?yàn)闆]有g(shù)etChild()方法,即使有,有那么多的兒子交給那一個(gè)呢?所以干錯(cuò)就不叫給兒子處理了.              
                  委托機(jī)制有什么好處?集中管理,如果我們寫了幾個(gè)類加載器,都去加載某個(gè)類,那么內(nèi)存中就有多份這個(gè)類的字節(jié)碼
                  能不能自己寫一個(gè)類叫java.lang.System?
          為了不讓我們寫System類,類加載采用委托機(jī)制,這樣可以保證爸爸優(yōu)先,也就是使用的永遠(yuǎn)是爸爸的(系統(tǒng)的)
          System類,而不是我們寫的System類.
          5,編寫自己的類加載器
          public static void main(String[] args) throws Exception {
                  String srcPath = args[0];
                  String destDir = args[1];
                  FileInputStream fis = new FileInputStream(srcPath);
                  String destFileName = srcPath.substring(srcPath.lastIndexOf('\\')+1);
                  String destPath = destDir + "\\" + destFileName;
                  FileOutputStream fos = new FileOutputStream(destPath);
                  cypher(fis,fos);
                  fis.close();
                  fos.close();
              }
              /**
               * 加密方法,同時(shí)也是解密方法
               * @param ips
               * @param ops
               * @throws Exception
               */
              private static void cypher(InputStream ips ,OutputStream ops) throws Exception{
                  int b = -1;
                  while((b=ips.read())!=-1){
                      ops.write(b ^ 0xff);//如果是1就變成0,如果是0就變成1
                  }
              }
          然后在新建一個(gè)類,通過上面的方法將新建的類的字節(jié)碼進(jìn)行加密:
          public class ClassLoaderAttachment extends Date { //為什么要繼承Date待會(huì)再說?
              public String toString(){
                  return "hello,itcast";
              }
          }
          并在工程里新建一個(gè)文件夾,用來保存加密后的class文件.


          那么這就需要使用我們自己的類加載器來進(jìn)行解密了.
          public class MyClassLoader extends ClassLoader{
              public static void main(String[] args) throws Exception {
                  String srcPath = args[0];
                  String destDir = args[1];
                  FileInputStream fis = new FileInputStream(srcPath);
                  String destFileName = srcPath.substring(srcPath.lastIndexOf('\\')+1);
                  String destPath = destDir + "\\" + destFileName;
                  FileOutputStream fos = new FileOutputStream(destPath);
                  cypher(fis,fos);
                  fis.close();
                  fos.close();
              }
              /**
               * 加密方法,同時(shí)也是解密方法
               * @param ips
               * @param ops
               * @throws Exception
               */
              private static void cypher(InputStream ips ,OutputStream ops) throws Exception{
                  int b = -1;
                  while((b=ips.read())!=-1){
                      ops.write(b ^ 0xff);//如果是1就變成0,如果是0就變成1
                  }
              }
              private String classDir;
              @Override
              protected Class<?> findClass(String name) throws ClassNotFoundException {
                  String classFileName = classDir + "\\" + name.substring(name.lastIndexOf('.')+1) + ".class";
                  try {
                      FileInputStream fis = new FileInputStream(classFileName);
                      ByteArrayOutputStream bos = new ByteArrayOutputStream();
                      cypher(fis,bos);
                      fis.close();
                      System.out.println("aaa");
                      byte[] bytes = bos.toByteArray();
                      return defineClass(bytes, 0, bytes.length);
                  } catch (Exception e) {
                      e.printStackTrace();
                  }
                  return null;
              }
              public MyClassLoader(){
              }
              public MyClassLoader(String classDir){
                  this.classDir = classDir;
              }
          }
          測(cè)試運(yùn)行代碼:
                  Class clazz = new MyClassLoader("myClass").loadClass("ClassLoaderAttachment");
                  //此處不能在使用ClassLoaderAttachment因?yàn)橐坏┯昧酥?
                  //系統(tǒng)的類加載器就會(huì)去加載,導(dǎo)致失敗,所以該類就繼承了Date類了.
                  Date date = (Date)clazz.newInstance();
                  System.out.println(date);
          運(yùn)行結(jié)果:



          6,一個(gè)類加載器的高級(jí)問題:
                  我們知道tomcat服務(wù)器,是一個(gè)大大的java程序,那么它就必須在JVM上運(yùn)行.
          這個(gè)大大的java程序內(nèi)部也寫了很多類加載器,它用這些類加載器去加載一些特定的類.注入servlet類.
          下面我們新建一個(gè)javaweb工程,新建一個(gè)servlet程序.
              public void doGet(HttpServletRequest request, HttpServletResponse response)
                      throws ServletException, IOException {
                  response.setContentType("text/html");
                  PrintWriter out = response.getWriter();
                  ClassLoader classload = this.getClass().getClassLoader();
                  while (classload != null) {
                      out.println(classload.getClass().getName()+"<br>");
                      classload = classload.getParent();
                  }
                  out.println();
                  out.close();
              }
          然后配置服務(wù)器,部署應(yīng)用程序,啟動(dòng)tomcat服務(wù)器.在頁面訪問我們這個(gè)servlet,在頁面打印的
          結(jié)果如下圖所示:

          這是從小到大排序的.
          現(xiàn)在呢?我想把該servlet打成jar包,放在ExtClassLoad類加載器加載的路徑.
          通過Eclipse即可完成


          posted on 2013-03-21 14:55 Mr.lu 閱讀(211) 評(píng)論(0)  編輯  收藏


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


          網(wǎng)站導(dǎo)航:
           
          <2013年3月>
          242526272812
          3456789
          10111213141516
          17181920212223
          24252627282930
          31123456

          導(dǎo)航

          統(tǒng)計(jì)

          常用鏈接

          留言簿(2)

          隨筆檔案

          文章檔案

          搜索

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜

          主站蜘蛛池模板: 永兴县| 岳西县| 洛阳市| 肇州县| 高淳县| 洛宁县| 双峰县| 佛学| 鄂温| 武清区| 康乐县| 罗江县| 安仁县| 科尔| 河南省| 遂昌县| 岐山县| 慈利县| 化德县| 钦州市| 文成县| 大理市| 颍上县| 剑阁县| 滨海县| 双流县| 和政县| 和平区| 休宁县| 邵阳市| 洛隆县| 沁源县| 金门县| 修武县| 平远县| 东莞市| 绍兴县| 乐安县| 怀远县| 东台市| 中西区|