真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

Java運(yùn)行時(shí)環(huán)境之ClassLoader類加載機(jī)制詳解

背景:聽說ClassLoader類加載機(jī)制是進(jìn)入BAT的必經(jīng)之路。

創(chuàng)新互聯(lián)是一家專業(yè)提供長(zhǎng)島企業(yè)網(wǎng)站建設(shè),專注與成都網(wǎng)站制作、做網(wǎng)站、H5開發(fā)、小程序制作等業(yè)務(wù)。10年已為長(zhǎng)島眾多企業(yè)、政府機(jī)構(gòu)等服務(wù)。創(chuàng)新互聯(lián)專業(yè)網(wǎng)絡(luò)公司優(yōu)惠進(jìn)行中。

ClassLoader總述:

普通的Java開發(fā)其實(shí)用到ClassLoader的地方并不多,但是理解透徹ClassLoader類的加載機(jī)制,無論是對(duì)我們編寫更高效的代碼還是進(jìn)BAT都大有裨益;而從“黃埔軍校”出來的我對(duì)ClassLoader的理解都是借鑒了很多書籍和博客,站在了各大博主的肩膀上,感謝你們!上菜,Classloader最主要的作用就是將Java字節(jié)碼文件(后綴為.class)加載到JVM中,JVM在啟動(dòng)時(shí)不會(huì)一次性加載所有的class文件,而是根據(jù)需要?jiǎng)討B(tài)加載class文件,畢竟一次性加載太多jar包的class文件JVM吃不消;下面主要研究Bootstrap ClassLoader、Extention ClassLoader和AppClassLoader這三種類加載器。

談到ClassLoader就想到我們安裝JDK的時(shí)候都會(huì)在控制臺(tái)輸入java、javac驗(yàn)證是否安裝成功,而這個(gè)javac就是Java ClassLoader,測(cè)試是否能把Java源文件正確編譯成Java字節(jié)碼文件,下面的截圖就是個(gè)javac的小例子,javac之后加載器把Java源文件編譯成TestClassLoader.class字節(jié)碼文件。

Java運(yùn)行時(shí)環(huán)境之ClassLoader類加載機(jī)制詳解

由于下面要講到ClassLoader的加載路徑,這里順便把Java的環(huán)境變量也復(fù)習(xí)一遍。

JAVA_HOME:

指的是安裝JDK的位置,如:JAVA_HOME="/Library/Java/JavaVirtualMachines/jdk1.8.0_191.jdk/Contents/Home" 。

PATH:

配置PATH(程序的路徑)的作用將就是能夠在命令行窗口直接鍵入程序的名字了,而不再需要鍵入它的全路徑,比如上面代碼中我用的到j(luò)avac和java兩個(gè)命令。如:PATH=".$PATH:$JAVA_HOME/bin" ;就是在JAVA_HOME路徑上添加了JDK下的bin目錄即可。

CLASSPATH:

CLASSPATH就是指向jar包的路徑,如:PATH=".$PATH:$JAVA_HOME/bin" ; "."表示當(dāng)前目錄。

ClassLoader類加載流程:

三個(gè)Class Loader的執(zhí)行順序是:Bootstrap CLassloder -> Extention ClassLoader -> AppClassLoader;

1、Bootstrap CLassloder是最頂層的加載類,主要是加載核心類庫(kù),也就是%JRE_HOME%\lib下的rt.jar、resources.jar、charsets.jar和class等資源;并且,可以通過啟動(dòng)JVM時(shí)指定-Xbootclasspath和路徑來改變Bootstrap ClassLoader的加載目錄,下面有個(gè)小荔子。

2、Extention ClassLoader是擴(kuò)展的類加載器,其加載的是目錄%JRE_HOME%\lib\ext目錄下的jar包和class文件;它同樣也可以加載-D java.ext.dirs選項(xiàng)指定的目錄。

3、Appclass Loader是用于加載當(dāng)前應(yīng)用的classpath的所有類,其也稱為SystemAppClass。

另外有興趣的還可以看下Launcher類的源碼,源碼中規(guī)定了三個(gè)加載器的環(huán)境屬性分別為B:sun.boot.class.path、E:java.ext.dirs和A:java.class.path;下面通過代碼來簡(jiǎn)單測(cè)試寫,如圖:

Java運(yùn)行時(shí)環(huán)境之ClassLoader類加載機(jī)制詳解

打印輸出結(jié)果:

BootstrapClassLoader:
        /Library/Java/JavaVirtualMachines/jdk1.8.0_191.jdk/Contents/Home/jre/lib/resources.jar:
            /Library/Java/JavaVirtualMachines/jdk1.8.0_191.jdk/Contents/Home/jre/lib/rt.jar:
                /Library/Java/JavaVirtualMachines/jdk1.8.0_191.jdk/Contents/Home/jre/lib/sunrsasign.jar:
                    /Library/Java/JavaVirtualMachines/jdk1.8.0_191.jdk/Contents/Home/jre/lib/jsse.jar:
                        /Library/Java/JavaVirtualMachines/jdk1.8.0_191.jdk/Contents/Home/jre/lib/jce.jar:
                            /Library/Java/JavaVirtualMachines/jdk1.8.0_191.jdk/Contents/Home/jre/lib/charsets.jar:
                                /Library/Java/JavaVirtualMachines/jdk1.8.0_191.jdk/Contents/Home/jre/lib/jfr.jar:
                                    /Library/Java/JavaVirtualMachines/jdk1.8.0_191.jdk/Contents/Home/jre/classes

ExtClassLoader:
        /Users/apple/Library/Java/Extensions:
            /Library/Java/JavaVirtualMachines/jdk1.8.0_191.jdk/Contents/Home/jre/lib/ext:
                /Library/Java/Extensions:/Network/Library/Java/Extensions:
                    /System/Library/Java/Extensions:/usr/lib/java

AppClassLoader:
        /TJT/Eclipse/workspace/tjt/bin:
            /Library/Java/JavaVirtualMachines/jdk1.8.0_191.jdk/Contents/Home/jre/lib/rt.jar

為了更好的理解三者之間加載的關(guān)系,我們來測(cè)試一個(gè)類的加載器和它的父類加載以及一些不是我們創(chuàng)建的類如String、Double、int等基礎(chǔ)類:

Java運(yùn)行時(shí)環(huán)境之ClassLoader類加載機(jī)制詳解

從上圖中可用看出,自己編寫的類Test2.class文件是由AppClassLoader加載的,并且AppClassLoader有父加載器ExtClassLoader,但ExtClassLoader的父加載器為null;Double.class這個(gè)Java基礎(chǔ)類的加載器為null,其父加載也為空且程序還會(huì)報(bào)空指針異常錯(cuò)誤;其實(shí)呢,Double.class是有Bootstrap CLassLoader加載的,也并不是每個(gè)加載器都有父加載器;總的來說就是JVM啟動(dòng)時(shí)通過Bootstrap類加載器加載rt.jar等核心jar包中的class文件,諸如一些int.class,String.class都是由它加載;JVM初始化sun.misc.Launcher并創(chuàng)建Extension ClassLoader和AppClassLoader實(shí)例,且將ExtClassLoader設(shè)置為AppClassLoader的父加載器;而Bootstrap雖然沒有父加載器,但是它卻可以作為一個(gè)ClassLoader的父加載器;另外,一個(gè)ClassLoader創(chuàng)建時(shí)如果沒有指定parent,那么它的parent默認(rèn)就是AppClassLoader;

雙親委托:

當(dāng)一個(gè)類加載器查找class和resource時(shí),是通過“委托模式”進(jìn)行的,它首先會(huì)判斷這個(gè)class是不是已經(jīng)加載成功,如果沒有加載的話它并不是自己進(jìn)行查找,而是先通過父加載器,然后遞歸下去,直到Bootstrap ClassLoader,如果Bootstrap classloader找到了,直接返回,如果沒有找到,則一級(jí)一級(jí)返回,最后是由自身去查找這些對(duì)象;這種機(jī)制就叫做雙親委托。

Java運(yùn)行時(shí)環(huán)境之ClassLoader類加載機(jī)制詳解

從上圖可用看出ClassLoader的加載序列,委托是從下往上,查找過程則是從上向下的,以下有幾個(gè)注意事項(xiàng):

1、一個(gè)AppClassLoader查找資源時(shí),首先會(huì)查看緩存是否有,若有則從緩存中獲取,否則委托給父加載器;

2.、重復(fù)第一步的遞歸操作,查詢類是否已被加載;

3.、如果ExtClassLoader也沒有加載過,則由Bootstrap ClassLoader加載,它首先也會(huì)查找緩存,如果沒有找到的話,就去找自己的規(guī)定的路徑下,也就是sun.mic.boot.class下面的路徑,找到就返回,找不到就讓子加載器自己去找。

4.、Bootstrap ClassLoader如果沒有查找成功,則ExtClassLoader自己在java.ext.dirs路徑中去查找,查找成功就返回,查找不成功則再向下讓子加載器找。

5.、若是ExtClassLoader查找不成功,則由ppClassLoader在java.class.path路徑下自己查找查找,找到就返回,如果沒有找到就讓子類找,如果沒有子類則會(huì)拋出各種異常。

自定義CLassLoader:

在ClassLoader中有四個(gè)很重要實(shí)用的方法loadClass()、findLoadedClass()、findClass()、defineClass(),可以用來創(chuàng)建屬于自己的類的加載方式;比如我們需要?jiǎng)討B(tài)加載一些東西,或者從C盤某個(gè)特定的文件夾加載一個(gè)class文件,又或者從網(wǎng)絡(luò)上下載class主內(nèi)容然后再進(jìn)行加載等。分三步搞定:

1、編寫一個(gè)類繼承ClassLoader抽象類;

2、重寫findClass()方法;

3、在findClass()方法中調(diào)用defineClass()方法即可實(shí)現(xiàn)自定義ClassLoader;

需求:自定義一個(gè)classloader其默認(rèn)加載路徑為"/TJT/Code"下的jar包和資源。首先創(chuàng)建一個(gè)Test.java,然后javac編譯并把生成的Test.class文件放到"/TJT/Code"路徑下,然后再編寫一個(gè)DiskClassLoader繼承ClassLoader,最后通過FindClassLoader的測(cè)試類,調(diào)用再Test.class里面的一個(gè)find()方法。

package www.baidu;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

public class DiskClassLoader extends ClassLoader{
//自定義classLoader能將class二進(jìn)制內(nèi)容轉(zhuǎn)換成Class對(duì)象
 private String myPath;
 
 public DiskClassLoader(String path) {
  myPath = path;
 }
 
 //findClass()方法中定義了查找class的方法
 @Override
 protected Class<?> findClass(String name) throws ClassNotFoundException{
  String fileName = getFileName(name);
  File file = new File(myPath,fileName);
  try {
   FileInputStream is = new FileInputStream(file);
   ByteArrayOutputStream bos = new ByteArrayOutputStream();
   int len = 0;
   try {
    while((len = is.read()) != -1) {
     bos.write(len);
    }
   } catch (IOException e) {
    e.printStackTrace();
   }
   byte[] data = bos.toByteArray();
   is.close();
   bos.close();
   //數(shù)據(jù)通過defineClass()生成了Class對(duì)象
   return defineClass(name, data,0,data.length );
  } catch (Exception e) {
   e.printStackTrace();
  }
  return super.findClass(name);
 }
 
 private String getFileName(String name) {
  int lastIndexOf = name.lastIndexOf('.');
  if (lastIndexOf == -1) {
   return name + ".class";
  }else {
   return name.substring(lastIndexOf + 1) + ".class";
  }
 }
}

測(cè)試結(jié)果如下:找到了自定義的加載路徑并且調(diào)用了類中的find()方法

Java運(yùn)行時(shí)環(huán)境之ClassLoader類加載機(jī)制詳解

package www.baidu;
import java.lang.reflect.Method;

public class FindClassLoader {
 public static void main(String[] args) throws ClassNotFoundException {
  //創(chuàng)建自定義classloader對(duì)象
  DiskClassLoader diskL = new DiskClassLoader("/TJT/Code");
  System.out.println("classloader is: "+diskL);
  try {
    //加載class文件
   Class clazz = diskL.loadClass("www.baidu.Test");
   if (clazz != null) {
    Object object = clazz.newInstance();
    Method declaredMethod = clazz.getDeclaredMethod("find", null);
    //通過反射調(diào)用Test類的find()方法
    declaredMethod.invoke(object, null);
   }
  } catch (Exception e) {
   e.printStackTrace();
  } 
 }
}

總結(jié):

除此之外,ClassLoader還可以進(jìn)行程序加密(比如你寫了比較騷的jar包),這樣我們就可以在程序中加載特定了類,并且這個(gè)類只能被我們自定義的加載器進(jìn)行加載,提高了程序的安全性,但是用的不多;反正我們?cè)陧?xiàng)目上是不允許用ClassLoader加密,寧愿裸奔,了解一下。另外就是tomcat的類加載機(jī)制也是遵循雙親委派機(jī)制的,并且大部分的加載機(jī)制和JVM類加載機(jī)制一樣,理解了Bootstrap ClassLoader、Extention ClassLoader和AppClassLoader這三種加載器后再看tomcat類的加載就可以橫著走了。

好了,以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問大家可以留言交流,謝謝大家對(duì)創(chuàng)新互聯(lián)的支持。


本文標(biāo)題:Java運(yùn)行時(shí)環(huán)境之ClassLoader類加載機(jī)制詳解
地址分享:http://weahome.cn/article/gjicop.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部