最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java類加載器層次結(jié)構(gòu)原理解析

 更新時間:2020年06月30日 10:08:05   作者:青蔥歲月  
這篇文章主要介紹了Java類加載器層次結(jié)構(gòu)原理解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下

類加載器的層次結(jié)構(gòu):

引導(dǎo)類加載器(bootstrap class loader)

  用來加載java的核心庫(JAVA_HOME/jre/lib/rt.jar,或sun.boot.class.path路徑下的內(nèi)容),是用原生代碼來實現(xiàn)的(C實現(xiàn)的),并不繼承自java.lang.ClassLoader。

  加載擴展類和應(yīng)用程序類加載器,并指定它們的父類加載器。

擴展類加載器(extensions class loader)

  用來加載java的擴展庫(JAVA_HOME/jre/lib/ext/*.jar,或java.ext.dirs路徑下的內(nèi)容)java虛擬機的實現(xiàn)會提供一個擴展庫目錄。該類加載器在此目錄里面查找并加載java類。

  有sun.miscLauncher$ExtClassLoader實現(xiàn),繼承自java.lang.ClassLoader

應(yīng)用程序類加載器(application class loader)

  它根據(jù)java應(yīng)用的類路徑(classpath,java.class.path路徑)來加載指定路徑的類,一般來說,java應(yīng)用的類都是由它來完成加載的

  由sun.misc.Launcher$AppClassLoader實現(xiàn),繼承自java.lang.ClassLoader

自定義類加載器

  開發(fā)人員可以通過繼承java.lang.ClassLoader類的方式實現(xiàn)自己的類加載器,以滿足一些特殊的需求。

說明:在java中由于類的加載采用的是雙親委托機制,上面幾種類加載器是父子關(guān)系,其中引導(dǎo)類加載器為基礎(chǔ)。

ClassLoader類介紹

作用:

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

  除此之外,ClassLoader還負(fù)責(zé)加載java應(yīng)用所需的資源文件,如圖像文件和配置文件等。

相關(guān)方法:

  • getParent()  返回該類加載器的父類加載器
  • loadClass(String name)  加載名稱為name的類,返回的結(jié)果是java.lang.Class類的實例
  • findClass(String name)  查找名稱為name的類,返回的結(jié)果是java.lang.Class類的實例
  • findLoadedClass(String name)  查找名稱為name的已經(jīng)被加載過的類,返回的結(jié)果是java.lang.Class類的實例
  • defineClass(String name,byte[] b,int off,int len)  把字節(jié)數(shù)組b中的內(nèi)容轉(zhuǎn)換成java類,返回的結(jié)果是java.lang.Class類的實例。這個方法被聲明為final的。
  • resolveClass(Class<?> c)  鏈接指定的java類。

代碼測試類加載器:

public class Demo02 {
  public static void main(String[] args) {
    System.out.println(ClassLoader.getSystemClassLoader());
    System.out.println(ClassLoader.getSystemClassLoader().getParent());;
    System.out.println(ClassLoader.getSystemClassLoader().getParent().getParent());;
  }
}

輸出:

sun.misc.Launcher$AppClassLoader@1016632

sun.misc.Launcher$ExtClassLoader@dc6a77

null

依次為應(yīng)用加載器、擴展加載器和引導(dǎo)加載器(但是引導(dǎo)加載為原生代碼所寫,因此獲取不到,為null)。

類加載器的代理模式:

代理模式:交給其他加載器來加載指定的類。

雙親委托機制:

  就是某個特定的類加載器在接到加載類的請求時,首先將加載任務(wù)委托給父類加載器,以此追溯,直到最高的爺爺輩的,如果父類加載器可以完成類加載任務(wù),就成功返回;只有父類加載器無法完成此加載任務(wù)時,才自己去加載。

  雙親委托機制是為了保證java核心庫的類型安全(這種機制就保證不會出現(xiàn)用戶自己能定義java.lang.Object類的情況)。

  類加載器除了用于加載類,也是安全的最基本的屏障。

雙親委托機制是代理模式的一種:

  并不是所有的類加載器都采用雙親委托機制。

  tomcat服務(wù)器類加載器也使用代理模式,所不同的是它是首先嘗試自己去加載某個類,如果找不到再代理給父類加載器。這與一般類加載器的順序是相反的。

自定義類加載器的流程:

  繼承:java.lang.ClassLoader

  首先檢查請求的類型是否已經(jīng)被這個類裝載器裝載到命名空間中,如果已經(jīng)裝載,則返回

  委派類將加載請求給父類加載器,如果父類加載器能夠完成,則返回父類加載器加載的Class實例

  調(diào)用本類加載器的findClass()方法,師徒獲取對應(yīng)的字節(jié)碼,如果獲取得到,則調(diào)用defineClass()導(dǎo)入類型到方法區(qū);如果獲取不到對應(yīng)的字節(jié)碼或者其它原因失敗,則返回異常給loadClass(),loadClass()轉(zhuǎn)拋異常,終止加載過程

  注:被兩個加載器加載的同一個類,Jvm不認(rèn)為是相同的類。

示例代碼如下:

package com.test;

import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

/**
 * 自定義文件系統(tǒng)加載器
 * @author We.lxk
 *
 */
public class FileSystemClassLoader extends ClassLoader{
  private String rootDir;
  
  public FileSystemClassLoader(String rootDir) {
    this.rootDir = rootDir;
  }
  
  private byte[] getClassData(String classname){    //com.test.User -> rootDir/com/test/User
    String path = rootDir +"/"+classname.replace(".", "/")+".class";
    //IOUtils 可以使用它將讀取的流數(shù)據(jù)轉(zhuǎn)換為字節(jié)數(shù)組
    InputStream is = null;
    ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
    try{
      is = new FileInputStream(path);
      
      byte[] buffer = new byte[1024];
      int temp = 0;
      while((temp=is.read(buffer))!=-1){
        baos.write(buffer, 0, temp);
      }
      return baos.toByteArray();
    }catch(Exception e){
      e.printStackTrace();
      return null;
    }finally{
        try {
          if(is!=null)
          is.close();
        } catch (IOException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
        }
        try {
          if(baos!=null)
          baos.close();
        } catch (IOException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
        }
    }
  }
  
  @Override
  public Class<?> loadClass(String name) throws ClassNotFoundException {
    Class<?> c = findLoadedClass(name);
    
    //應(yīng)該先查詢有沒有加載過這個類。已經(jīng)加載,則直接返回加載好的類。
    if(c!=null){
      return c;
    }else{
      ClassLoader parent = this.getParent();
      try{
        //System.out.println("hello");
        c = parent.loadClass(name);          //委派給父類加載
      }catch(Exception e){
        //e.printStackTrace();
      }
      if(c!=null){
        return c;
      }else{
        byte[] classData = getClassData(name);
        if(classData==null){
          throw new ClassNotFoundException();
        }else{
          c = defineClass(name, classData, 0, classData.length);
        }
      }
    }
    return c;
  }
}

測試代碼:

package com.test;

/**
 *  測試自定義的FileSystemClassLoader 
 * @author We.lxk
 *
 */
public class Demo03 {
  public static void main(String[] args) throws Exception {
    FileSystemClassLoader loader = new FileSystemClassLoader("D:/myJava");
    FileSystemClassLoader loader2 = new FileSystemClassLoader("D:/myJava");
    
    Class<?> c = loader.loadClass("com.test.Demos");
    Class<?> c2 = loader.loadClass("com.test.Demos");
    Class<?> c3 = loader2.loadClass("com.test.Demos");
    
    Class<?> c4 = loader2.loadClass("java.lang.String");
    Class<?> c5 = loader.loadClass("com.test.Demo");
    
    
    System.out.println(c.hashCode()+" "+c.getClassLoader());
    System.out.println(c2.hashCode()+" "+c2.getClassLoader());
    System.out.println(c3.hashCode()+" "+c3.getClassLoader());
    System.out.println(c4.hashCode()+" "+c4.getClassLoader());
    System.out.println(c5.hashCode()+" "+c5.getClassLoader());
    //System.out.println(.getClassLoader());
  }
}

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Spring如何通過@Lazy注解解決構(gòu)造方法循環(huán)依賴問題

    Spring如何通過@Lazy注解解決構(gòu)造方法循環(huán)依賴問題

    循環(huán)依賴其實就是循環(huán)引用,也就是兩個或則兩個以上的bean互相持有對方,最終形成閉環(huán),這篇文章主要給大家介紹了關(guān)于Spring如何通過@Lazy注解解決構(gòu)造方法循環(huán)依賴問題的相關(guān)資料,需要的朋友可以參考下
    2023-03-03
  • java 字浮串提取方法匯集

    java 字浮串提取方法匯集

    用方法toCharArray public char[] toCharArray()
    2008-10-10
  • iOS socket網(wǎng)絡(luò)編程實例詳解

    iOS socket網(wǎng)絡(luò)編程實例詳解

    socket是一個針對TCP和UDP編程的接口,你可以借助它建立TCP連接等。這篇文章主要介紹了iOS socket網(wǎng)絡(luò)編程 ,需要的朋友可以參考下
    2017-03-03
  • SpringBoot 集成 Druid過程解析

    SpringBoot 集成 Druid過程解析

    這篇文章主要介紹了SpringBoot 集成 Druid過程解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-09-09
  • java SpringBoot自定義注解,及自定義解析器實現(xiàn)對象自動注入操作

    java SpringBoot自定義注解,及自定義解析器實現(xiàn)對象自動注入操作

    這篇文章主要介紹了java SpringBoot自定義注解,及自定義解析器實現(xiàn)對象自動注入操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-08-08
  • Java ThreadLocal的詳細(xì)解釋

    Java ThreadLocal的詳細(xì)解釋

    這篇文章主要介紹了快速了解Java中ThreadLocal類,介紹了ThreadLocal 是什么,ThreadLocal的作用,ThreadLocal 原理等相關(guān)內(nèi)容,具有一定參考價值,需要的朋友可以了解下。
    2021-11-11
  • spring-data-redis連接操作redis的實現(xiàn)

    spring-data-redis連接操作redis的實現(xiàn)

    spring-data-redis則是對Jedis進(jìn)行了高度封裝,使用起來非常方便。本文主要介紹了spring-data-redis連接操作redis的實現(xiàn),感興趣的可以了解一下
    2021-07-07
  • Spring?Boot中記錄用戶系統(tǒng)操作流程

    Spring?Boot中記錄用戶系統(tǒng)操作流程

    這篇文章主要介紹了如何在Spring?Boot中記錄用戶系統(tǒng)操作流程,將介紹如何在Spring?Boot中使用AOP(面向切面編程)和日志框架來實現(xiàn)用戶系統(tǒng)操作流程的記錄,需要的朋友可以參考下
    2023-07-07
  • Java基礎(chǔ)詳解之包裝類的裝箱拆箱

    Java基礎(chǔ)詳解之包裝類的裝箱拆箱

    這篇文章主要介紹了Java基礎(chǔ)詳解之包裝類的裝箱拆箱,文中有非常詳細(xì)的代碼示例,對正在學(xué)習(xí)java的小伙伴們有非常好的幫助,需要的朋友可以參考下
    2021-04-04
  • logback 自定義Pattern模板教程

    logback 自定義Pattern模板教程

    這篇文章主要介紹了logback 自定義Pattern模板教程,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-07-07

最新評論

桐城市| 澄迈县| 岳普湖县| 建阳市| 海口市| 福泉市| 延安市| 沙雅县| 元阳县| 雅安市| 南召县| 宝清县| 肃宁县| 西吉县| 确山县| 普兰店市| 伊宁县| 松溪县| 和硕县| 贺州市| 永吉县| 深圳市| 石林| 铅山县| 怀仁县| 南漳县| 南和县| 湖北省| 太白县| 铜陵市| 工布江达县| 高唐县| 永登县| 固镇县| 加查县| 嘉定区| 京山县| 凤山县| 宁明县| 松潘县| 沙田区|