手寫一個類加載器demo


1、什么是類加載器?

 

 

 2、加載方式

ClassLoader類加載器,主要的作用是將class文件加載到jvm虛擬機中。jvm啟動的時候,並不是一次性加載所有的類,而是根據需要動態去加載類,主要分為隱式加載和顯示加載。

隱式加載:程序代碼中不通過調用ClassLoader來加載需要的類,而是通過JVM類自動加載需要的類到內存中。例如,當我們在類中繼承或者引用某個類的時候,

JVM在解析當前這個類的時,發現引用的類不在內存中,那么就會自動將這些類加載到內存中。

顯示加載:代碼中通過Class.forName(),this.getClass.getClassLoader.LoadClass(),自定義類加載器中的findClass()方法等。

顯示加載的時候,當我們獲取到class對象之后,需要調用class對象的new instans()生成實例。

3、類加載器的種類及作用

(1)BootStrap ClassLoader:主要加載%JRE_HOME%\lib下的rt.jar、resources.jar、charsets.jar和class等。可以通System.getProperty("sun.boot.class.path")

 

(2)Extention ClassLoader:主要加載目錄%JRE_HOME%\lib\ext目錄下的jar包和class文件。也可以通過System.out.println(System.getProperty("java.ext.dirs"))查看加載類文件的路徑。

 

(3)AppClassLoader:主要加載當前應用下的classpath路徑下的類。之前我們在環境變量中配置的classpath就是指定AppClassLoader的類加載路徑。

(4)用戶自定義類加載器

4、繼承關系

 

 

 

 

 

 

 

5、雙親委派機制

例如:當jvm要加載Test.class的時候,

  (1)首先會到自定義加載器中查找,看是否已經加載過,如果已經加載過,則返回字節碼。

  (2)如果自定義加載器沒有加載過,則詢問上一層加載器(即AppClassLoader)是否已經加載過Test.class。

  (3)如果沒有加載過,則詢問上一層加載器(ExtClassLoader)是否已經加載過。

  (4)如果沒有加載過,則繼續詢問上一層加載(BoopStrap ClassLoader)是否已經加載過。

  (5)如果BoopStrap ClassLoader依然沒有加載過,則到自己指定類加載路徑下("sun.boot.class.path")查看是否有Test.class字節碼,有則返回,沒有通

知下一層加載器ExtClassLoader到自己指定的類加載路徑下(java.ext.dirs)查看。

  (6)依次類推,最后到自定義類加載器指定的路徑還沒有找到Test.class字節碼,則拋出異常ClassNotFoundException。如下圖:

 

 

 7、自定義loaderclass

(1)新建一個java文件,保存在相應的目錄。

 

 

 

 

 

 (2)用cmd命令進入到world類的上級目錄,運行javac命令,生成.class文件。

 

 

 (3)創建自己定義的classload類。

//繼承ClassLoader類,重寫findclass方法。
public class MyClassloader extends ClassLoader {

  private String path;
  private String classloaderName;

  public MyClassloader(String path,String classloaderName){
    this.path = path;
    this.classloaderName = classloaderName;
  }

  //用於尋找類文件
  @Override
  public Class findClass(String name){
    byte[] b =loadClassData(name);
    return defineClass(name,b,0,b.length);
  }

  public byte[] loadClassData(String name) {
    name = path + name + ".class";
    InputStream in = null;
    ByteArrayOutputStream out = null;

    try {
      in = new FileInputStream(new File(name));
      out = new ByteArrayOutputStream();
      int i = 0;
      while ((i = in.read()) != -1){
      out.write(i);
      }
    } catch (Exception e) {
      e.printStackTrace();
    }finally {
      try {
        out.close();
        in.close();
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
    return out.toByteArray();
  }
}

(4)創建測試類,測試結果。

public class ClassLoderCheck {

  public static void main(String[] args)
      throws IllegalAccessException, InstantiationException, ClassNotFoundException {
    MyClassloader classloader = new MyClassloader("D:/jvm/", "myclasscloderz");
    Class c = classloader.loadClass("World");
    System.out.println(c.getClassLoader());
    System.out.println(c.getClassLoader().getParent());
    System.out.println(c.getClassLoader().getParent().getParent());
    c.newInstance();
  }
}

運行結果為:

 

 自定義類加載器的作用:jvm自帶的三個加載器只能加載指定路徑下的類字節碼。如果某個情況下,我們需要加載應用程序之外的類文件呢?比如本地D盤下的,或者去加載網絡上的某個類文件,這種情況就可以使用自定義加載器了。

參考網址:cnblogs.com/gdpuzxs/p/7044963.html

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM