<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    JimmyJin
    走在架構師的大道上,學習的樂趣就在于將知識應用于具體實踐中,在實戰中實現知識的價值。
    posts - 4,comments - 0,trackbacks - 0

    類加載器基本概念

    顧名思義,類加載器(class loader)用來加載 Java 類到 Java 虛擬機中。一般來說,Java 虛擬機使用 Java 類的方式如下:Java 源程序(.java 文件)在經過 Java 編譯器編譯之后就被轉換成 Java 字節代碼(.class 文件)。類加載器負責讀取 Java 字節代碼,并轉換成 java.lang.Class類的一個實例。每個這樣的實例用來表示一個 Java 類。通過此實例的 newInstance()方法就可以創建出該類的一個對象。實際的情況可能更加復雜,比如 Java 字節代碼可能是通過工具動態生成的,也可能是通過網絡下載的。
    基本上所有的類加載器都是 java.lang.ClassLoader類的一個實例。

    public abstract class ClassLoader
    extends Object

    類加載器的樹狀組織結構

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

    • 引導類加載器(bootstrap class loader):它用來加載 Java 的核心庫,是用原生代碼來實現的,并不繼承自java.lang.ClassLoader。其父類加載器為NULL。
    • 擴展類加載器(extensions class loader):它用來加載 Java 的擴展庫。Java 虛擬機的實現會提供一個擴展庫目錄。該類加載器在此目錄里面查找并加載 Java 類。
    • 系統類加載器(system class loader):它根據 Java 應用的類路徑(CLASSPATH)來加載 Java 類。一般來說,Java 應用的類都是由它來完成加載的。可以通過 ClassLoader.getSystemClassLoader()來獲取它。

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

    除了引導類加載器之外,所有的類加器都有一個父類加載器。通過ClassLoader中給出的 getParent()方法可以得到。對于系統提供的類加載器來說,系統類加載器的父類加載器是擴展類加載器,而擴展類加載器的父類加載器是引導類加載器;對于開發人員編寫的類加載器來說,其父類加載器是加載此類加載器 Java 類的類加載器。因為類加載器 Java 類如同其它的 Java 類一樣,也是要由類加載器來加載的。一般來說,開發人員編寫的類加載器的父類加載器是系統類加載器。類加載器通過這種方式組織起來,形成樹狀結構。樹的根節點就是引導類加載器。圖 1中給出了一個典型的類加載器樹狀組織結構示意圖,其中的箭頭指向的是父類加載器。


    圖 1. 類加載器樹狀組織結構示意圖
    類加載器樹狀組織結構示意圖
    類是由它的全名和類加載器來確定的,由此我們可以看到一個有趣的現象即
    在同一個虛擬機中,可以有兩個類,它們的類名和包名都是相同的。這項技術在加載來自多處的代碼時非常有用如熱布署就是應用這一特性來實現的。
    JVM啟動時,首先加載類加載器及其相對應的字節碼(class),其順序為: 
    先是bootstrap classloader------(rt.jar,然后是extension classloader ------(jre/lib/ext) ,最后才是system classloader ------(CLASSPATH 大家會發現加載的Class越是重要的越在靠前面。這樣做的原因是出于安全性的考慮,試想如果system classloader“親自”加載了一個具有破壞性的“java.lang.System”類的后果吧。這種委托機制保證了用戶即使具有一個這樣的類,也把它加入到了類路徑中,但是它永遠不會被載入,因為這個類總是由bootstrap classloader來加載的。大家可以執行一下以下的代碼: 
        System.out.println(System.class.getClassLoader()); 
    將會看到結果是null,這就表明java.lang.System是由bootstrap classloader加載的,因為bootstrap classloader(用C++實現的)不是一個真正的ClassLoader實例,而是由JVM實現的。
    類的加載過程:
    我們知道每個類都有它自已的類加載器(Class.getClassLoader),
    除了引導類加載器之外,所有的類加器都有一個父類加載器。通過ClassLoader中給出的 getParent()方法可以得到。對于系統提供的類加載器來說,系統類加載器的父類加載器是擴展類加載器,而擴展類加載器的父類加載器是引導類加載器;對于開發人員編寫的類加載器來說,其父類加載器是加載此類加載器 Java 類的類加載器。

     

    編寫你自已的類加載器:
    只需要繼承ClassLoader類,然后重寫其findClass(String classname)即可。
    ClassLoader超類的loadClass方法用于將類的加載操作委托給其父類加載器去進行,
    只有當類尚未加載并且其所有父類加載器也沒有加載此類時,才能調用你自已的類加載器中的findclass方法。
    例法:
    class CryptoClassLoader extends ClassLoader
    {
       /**
        * Constructs a crypto class loader.
        * @param k the decryption key
        */
       public CryptoClassLoader(int k)
       {
          key = k;
       }
       protected Class findClass(String name
       {
          byte[] classBytes = null;
             try {
    classBytes = loadClassBytes(name);
    } catch (IOException e) {
    e.printStackTrace();
    }
         //defineClass 方法將一個 byte 數組轉換為 Class 類的實例。
          Class cl = defineClass(name, classBytes, 0, classBytes.length);
          if (cl == null)
    try {
    throw new ClassNotFoundException(name);
    } catch (ClassNotFoundException e) {
    e.printStackTrace();
    }
          return cl;
       }
       /**
        * Loads and decrypt the class file bytes.
        * @param name the class name
        * @return an array with the class file bytes
        */
       private byte[] loadClassBytes(String name) throws IOException
       {
     // String cname="classes/com/jimmy/corejava/classloaderTest"+"/"+name+".class";
         String cname="classes/com/jimmy/corejava/classloaderTest"+"/"+name+".class";
     
          FileInputStream in = null;
          in = new FileInputStream(cname);
          try
          {
             ByteArrayOutputStream buffer = new ByteArrayOutputStream();
             int ch;
             while ((ch = in.read()) != -1)
             {
            buffer.write(ch);
             }
             in.close();
             return buffer.toByteArray();
          }
          finally
          {
             in.close();
          }
       }
       private int key;
    }
    為方便測試時,我們可事先給無法找到類的路徑,以防止其其父類加載器加載其類,這們強迫它調用我們的類加載器,然后在我們的findclass、loadClassBytes 方法中給出能找到此類的路徑,這樣就能得到我們的目的了。
    public class ClassLoaderTest
    {
       public static void main(String[] args)
       {
         
    //   String firstClass="v2ch09.ClassLoaderTest.Calculator";
      String firstClass="FirstClass";
      try {
            ClassLoader loader = new CryptoClassLoader(Integer.parseInt("3"));
    System.out.println("=====>"+ClassLoaderTest.class.getClassLoader().toString());
    Object fl= loader.loadClass(firstClass).newInstance();
    System.out.println("=====>"+fl.getClass().getClassLoader().toString());
    System.out.println(System.class.getClassLoader()); 
    } catch (ClassNotFoundException e) {
    e.printStackTrace();
    } catch (InstantiationException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    } catch (IllegalAccessException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
       }
    }
    打印結果為:
    =====>sun.misc.Launcher$AppClassLoader@addbf1
    =====>v2ch09.ClassLoaderTest.CryptoClassLoader@61de33
    運用自定義的類加載器,我們可以實現代碼的加密、解密等。
    posted on 2012-05-30 22:35 jimmy2009 閱讀(370) 評論(0)  編輯  收藏

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


    網站導航:
     
    主站蜘蛛池模板: 久久国产免费一区| 国产精品亚洲综合久久| 无码免费又爽又高潮喷水的视频 | 亚洲狠狠狠一区二区三区| 真人做A免费观看| 91久久精品国产免费一区| 亚洲综合一区二区三区四区五区| 久久精品一本到99热免费| 亚洲中文字幕无码久久| 亚洲尤码不卡AV麻豆| 好爽又高潮了毛片免费下载| 国产在线精品观看免费观看| 亚洲中文字幕久久久一区| 亚洲精品色午夜无码专区日韩| 18禁在线无遮挡免费观看网站| 亚洲AV一宅男色影视| 国产成人免费a在线视频app| 一区二区三区福利视频免费观看| 亚洲AV中文无码字幕色三| 免费无码又爽又高潮视频| 一级做a爰全过程免费视频| 一区二区三区视频免费| 伊人久久五月丁香综合中文亚洲| 四虎影视精品永久免费| 91福利视频免费观看| WWW免费视频在线观看播放| 亚洲国产精品无码久久九九大片| 国产精品亚洲高清一区二区| 最近免费中文字幕视频高清在线看| 亚洲av无码专区在线电影| 久久精品亚洲精品国产色婷| 国产午夜亚洲精品理论片不卡| 精品四虎免费观看国产高清午夜| 亚洲欧洲国产精品久久| 亚洲AV无码一区东京热久久| 亚洲日本中文字幕天堂网| 麻豆国产人免费人成免费视频| 无码毛片一区二区三区视频免费播放| 亚洲中文字幕一二三四区| 亚洲国产成人无码av在线播放| 日韩成全视频观看免费观看高清|