成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Java類加載器詳解

Baaaan / 1274人閱讀

摘要:當(dāng)一個(gè)文件是通過(guò)網(wǎng)絡(luò)傳輸并且可能會(huì)進(jìn)行相應(yīng)的加密操作時(shí),需要先對(duì)文件進(jìn)行相應(yīng)的解密后再加載到內(nèi)存中,這種情況下也需要編寫(xiě)自定義的并實(shí)現(xiàn)相應(yīng)的邏輯

Java虛擬機(jī)中的類加載有三大步驟:,鏈接,初始化.其中加載是指查找字節(jié)流(也就是由Java編譯器生成的class文件)并據(jù)此創(chuàng)建類的過(guò)程,這中間我們需要借助類加載器來(lái)查找字節(jié)流.

Java虛擬機(jī)默認(rèn)類加載器

Java虛擬機(jī)提供了3種類加載器,啟動(dòng)(Bootstrap)類加載器、擴(kuò)展(Extension)類加載器、應(yīng)用(Application)類加載器.除了啟動(dòng)類加載器外,其他的類加載器都是java.lang.ClassLoader的子類.啟動(dòng)類加載器由C++語(yǔ)言實(shí)現(xiàn),沒(méi)有對(duì)應(yīng)的Java對(duì)象,它負(fù)責(zé)將 /lib路徑下的核心類庫(kù)或-Xbootclasspath參數(shù)指定的路徑下的jar包加載到內(nèi)存中.?dāng)U展類加載器是指sun.misc.Launcher$ExtClassLoader類,由Java語(yǔ)言實(shí)現(xiàn),是Launcher的靜態(tài)內(nèi)部類,它負(fù)責(zé)加載/lib/ext目錄下或者由系統(tǒng)變量-Djava.ext.dir指定位路徑中的類庫(kù),他的父類加載器是null.應(yīng)用類加載器是指sun.misc.Launcher$AppClassLoader類,他負(fù)責(zé)加載應(yīng)用程序路徑下的類,這里路徑指java -classpath或-D java.class.path 指定的路徑,他的父類加載器是擴(kuò)展類加載器.

注意這里面的父子類加載器并不是繼承的關(guān)系,只是ClassLoader類中的parent屬性.我們來(lái)看Launcher類中創(chuàng)建擴(kuò)展類加載器的代碼:

public ExtClassLoader(File[] var1) throws IOException {
      super(getExtURLs(var1), (ClassLoader)null, Launcher.factory);
      SharedSecrets.getJavaNetAccess().getURLClassPath(this).initLookupCache(this);
    }

這里設(shè)置了其父加載器為null.

雙親委派機(jī)制

Java虛擬機(jī)在加載類時(shí)默認(rèn)采用的是雙親委派機(jī)制,即當(dāng)一個(gè)類加載器接收到加載請(qǐng)求時(shí),會(huì)將請(qǐng)求轉(zhuǎn)發(fā)到父類加載器,如果父類加載器在路徑下沒(méi)有找到該類,才會(huì)交給子類加載器去加載.我們來(lái)看ClassLoader中l(wèi)aodClass方法:

protected Class loadClass(String name, boolean resolve)
        throws ClassNotFoundException
    {
        synchronized (getClassLoadingLock(name)) {
            // 首先判斷類是否已加載過(guò),加載過(guò)就直接返回
            Class c = findLoadedClass(name);
            if (c == null) {
                long t0 = System.nanoTime();
                try {
                    if (parent != null) {
                        //有父類加載器,調(diào)用父加載器的loadClass
                        c = parent.loadClass(name, false);
                    } else {
                        //調(diào)用Bootstrap Classloader
                        c = findBootstrapClassOrNull(name);
                    }
                } catch (ClassNotFoundException e) {
                    // ClassNotFoundException thrown if class not found
                    // from the non-null parent class loader
                }

                if (c == null) {
                    long t1 = System.nanoTime();
                    //到自己指定類加載路徑下查找是否有class字節(jié)碼
                    c = findClass(name);

                    // this is the defining class loader; record the stats
                    sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
                    sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
                    sun.misc.PerfCounter.getFindClasses().increment();
                }
            }
            if (resolve) {
                resolveClass(c);
            }
            return c;
        }
    }

通過(guò)這種層級(jí)我們可以避免類的重復(fù)加載,當(dāng)父親已經(jīng)加載了該類時(shí),就沒(méi)有必要子類加載器再加載一次。其次也考慮到安全因素,比如我們自己寫(xiě)一個(gè)java.lang.String的類,通過(guò)雙親委派機(jī)制傳遞到啟動(dòng)類加載器,而啟動(dòng)類加載器在核心Java API發(fā)現(xiàn)這個(gè)名字的類,發(fā)現(xiàn)該類已被加載,并不會(huì)重新加載我們新寫(xiě)的java.lang.String,而直接返回已加載過(guò)的String.class,這樣保證生成的對(duì)象是同一種類型.

自定義類加載器

除了jvm自身提供的類加載器,我們還可以自定義類加載器,我們先寫(xiě)一個(gè)Person類

public class Person {

  private int age;

  private String name;

  //省略getter/setter方法
}

我們先看他是由哪個(gè)類加載器加載的.

public class TestJava {

  public static void main(String[] args) throws Exception {
    Person person = new Person();
    System.out.println("person是由" + person.getClass().getClassLoader() + "加載的");
  }
}

運(yùn)行結(jié)果如下:

我們把Person.class放置在其他目錄下

再運(yùn)行會(huì)發(fā)生什么,在上面的loadClass方法中其實(shí)已經(jīng)有了答案,會(huì)拋出ClassNotFoundException,因?yàn)樵谥付窂较虏檎也坏阶止?jié)碼.

我們現(xiàn)在寫(xiě)一個(gè)自定義的類加載器,讓他能夠去加載person類,很簡(jiǎn)單,我們只需要繼承ClassLoader并重寫(xiě)findClass方法,這里面寫(xiě)查找字節(jié)碼的邏輯.

public class PersonCustomClassLoader extends ClassLoader {

  private String classPath;

  public PersonCustomClassLoader(String classPath) {
    this.classPath = classPath;
  }

  private byte[] loadByte(String name) throws Exception {
    name = name.replaceAll(".", "/");
    FileInputStream fis = new FileInputStream(classPath + "/" + name
        + ".class");
    int len = fis.available();
    byte[] data = new byte[len];
    fis.read(data);
    fis.close();
    return data;

  }

  protected Class findClass(String name) throws ClassNotFoundException {
    try {
      byte[] data = loadByte(name);
      return defineClass(name, data, 0, data.length);
    } catch (Exception e) {
      e.printStackTrace();
      throw new ClassNotFoundException();
    }
  }
}

我們來(lái)測(cè)試一下:

public class TestJava {

  public static void main(String[] args) throws Exception {
    PersonCustomClassLoader classLoader = new PersonCustomClassLoader("/home/shenxinjian");
    Class pClass = classLoader.loadClass("me.shenxinjian.algorithm.Person");
    System.out.println("person是由" + pClass.getClassLoader() + "類加載器加載的");

  }
}

測(cè)試結(jié)果如下:

編寫(xiě)自定義類加載器的意義

當(dāng)class文件不在classPath路徑下,如上面那種情況,默認(rèn)系統(tǒng)類加載器無(wú)法找到該class文件,在這種情況下我們需要實(shí)現(xiàn)一個(gè)自定義的classLoader來(lái)加載特定路徑下的class文件來(lái)生成class對(duì)象。

當(dāng)一個(gè)class文件是通過(guò)網(wǎng)絡(luò)傳輸并且可能會(huì)進(jìn)行相應(yīng)的加密操作時(shí),需要先對(duì)class文件進(jìn)行相應(yīng)的解密后再加載到JVM內(nèi)存中,這種情況下也需要編寫(xiě)自定義的ClassLoader并實(shí)現(xiàn)相應(yīng)的邏輯

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/73405.html

相關(guān)文章

  • 關(guān)于ClassLoader的學(xué)習(xí)筆記,詳解

    摘要:它負(fù)責(zé)將的字節(jié)碼形式轉(zhuǎn)換成內(nèi)存形式的對(duì)象。先使用工具對(duì)字節(jié)碼文件進(jìn)行加密,運(yùn)行時(shí)使用定制的先解密文件內(nèi)容再加載這些解密后的字節(jié)碼。的方法是需要子類來(lái)覆蓋的,不同的加載器將使用不同的邏輯來(lái)獲取目標(biāo)類的字節(jié)碼。 ClassLoader 詳解 ClassLoader 做什么的? 延遲加載 各司其職 ClassLoader 傳遞性 雙親委派 Class.forName 自定義加載器 Clas...

    zgbgx 評(píng)論0 收藏0
  • JVM_加載機(jī)制詳解

    摘要:加載器種類啟動(dòng)類加載器在中用來(lái)加載自身需要的類,實(shí)現(xiàn),用來(lái)加載。那么就能保證的類會(huì)被優(yōu)先加載,限制了使用者對(duì)系統(tǒng)的影響。這種方式下就完成類加載器的雙親委派機(jī)制此處會(huì)將作為參數(shù)傳入進(jìn)去實(shí)際上是調(diào)用了方法 Class 文件的裝載流程 (類加載過(guò)程) 加載 -> 連接 (驗(yàn)證 -> 準(zhǔn)備 -> 解析) -> 初始化 -> 使用 -> 卸載 加載 加載階段,jvm 會(huì)通過(guò)類名獲取到此類的字節(jié)碼...

    MasonEast 評(píng)論0 收藏0
  • Java面試 32個(gè)核心必考點(diǎn)完全解析

    摘要:如問(wèn)到是否使用某框架,實(shí)際是是問(wèn)該框架的使用場(chǎng)景,有什么特點(diǎn),和同類可框架對(duì)比一系列的問(wèn)題。這兩個(gè)方向的區(qū)分點(diǎn)在于工作方向的側(cè)重點(diǎn)不同。 [TOC] 這是一份來(lái)自嗶哩嗶哩的Java面試Java面試 32個(gè)核心必考點(diǎn)完全解析(完) 課程預(yù)習(xí) 1.1 課程內(nèi)容分為三個(gè)模塊 基礎(chǔ)模塊: 技術(shù)崗位與面試 計(jì)算機(jī)基礎(chǔ) JVM原理 多線程 設(shè)計(jì)模式 數(shù)據(jù)結(jié)構(gòu)與算法 應(yīng)用模塊: 常用工具集 ...

    JiaXinYi 評(píng)論0 收藏0
  • Java反射機(jī)制詳解

    摘要:反射機(jī)制的應(yīng)用實(shí)例在泛型為的中存放一個(gè)類型的對(duì)象。工廠模式可以參考現(xiàn)在我們利用反射機(jī)制實(shí)現(xiàn)工廠模式,可以在不修改工廠類的情況下添加任意多個(gè)子類。 學(xué)習(xí)交流群:669823128java 反射 定義 功能 示例概要:Java反射機(jī)制詳解| |目錄 1反射機(jī)制是什么 2反射機(jī)制能做什么 3反射機(jī)制的相關(guān)API 通過(guò)一個(gè)對(duì)象獲得完整的包名和類名 實(shí)例化Class類對(duì)象 獲取一個(gè)對(duì)象的父類與...

    paraller 評(píng)論0 收藏0
  • 四年來(lái)Android面試大綱,作為一個(gè)Android程序員

    摘要:再附一部分架構(gòu)面試視頻講解本文已被開(kāi)源項(xiàng)目學(xué)習(xí)筆記總結(jié)移動(dòng)架構(gòu)視頻大廠面試真題項(xiàng)目實(shí)戰(zhàn)源碼收錄 Java反射(一)Java反射(二)Java反射(三)Java注解Java IO(一)Java IO(二)RandomAccessFileJava NIOJava異常詳解Java抽象類和接口的區(qū)別Java深拷貝和淺拷...

    不知名網(wǎng)友 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<