創(chuàng)新互聯(lián)www.cdcxhl.cn八線動態(tài)BGP香港云服務(wù)器提供商,新人活動買多久送多久,劃算不套路!
創(chuàng)新互聯(lián)公司網(wǎng)站建設(shè)公司,提供成都網(wǎng)站制作、網(wǎng)站設(shè)計(jì),網(wǎng)頁設(shè)計(jì),建網(wǎng)站,PHP網(wǎng)站建設(shè)等專業(yè)做網(wǎng)站服務(wù);可快速的進(jìn)行網(wǎng)站開發(fā)網(wǎng)頁制作和功能擴(kuò)展;專業(yè)做搜索引擎喜愛的網(wǎng)站,是專業(yè)的做網(wǎng)站團(tuán)隊(duì),希望更多企業(yè)前來合作!首先我想從宏觀上介紹一下Java虛擬機(jī)的工作原理。從最初的我們編寫的Java源文件(.java文件)是如何一步步執(zhí)行的,如下圖所示,首先Java源文件經(jīng)過前端編譯器(javac或ECJ)將.java文件編譯為Java字節(jié)碼文件,然后JRE加載Java字節(jié)碼文件,載入系統(tǒng)分配給JVM的內(nèi)存區(qū),然后執(zhí)行引擎解釋或編譯類文件,再由即時(shí)編譯器將字節(jié)碼轉(zhuǎn)化為機(jī)器碼。主要介紹下圖中的類加載器和運(yùn)行時(shí)數(shù)據(jù)區(qū)兩個(gè)部分。
類加載
類加載指將類的字節(jié)碼文件(.class)中的二進(jìn)制數(shù)據(jù)讀入內(nèi)存,將其放在運(yùn)行時(shí)數(shù)據(jù)區(qū)的方法區(qū)內(nèi),然后在堆上創(chuàng)建java.lang.Class對象,封裝類在方法區(qū)內(nèi)的數(shù)據(jù)結(jié)構(gòu)。類加載的最終產(chǎn)品是位于堆中的類對象,類對象封裝了類在方法區(qū)內(nèi)的數(shù)據(jù)結(jié)構(gòu),并且向JAVA程序提供了訪問方法區(qū)內(nèi)數(shù)據(jù)結(jié)構(gòu)的接口。如下是類加載器的層次關(guān)系圖。
啟動類加載器(BootstrapClassLoader):在JVM運(yùn)行時(shí)被創(chuàng)建,負(fù)責(zé)加載存放在JDK安裝目錄下的jre\lib的類文件,或者被-Xbootclasspath參數(shù)指定的路徑中,并且能被虛擬機(jī)識別的類庫(如rt.jar,所有的java.*開頭的類均被Bootstrap ClassLoader加載)。啟動類無法被JAVA程序直接引用。
擴(kuò)展類加載器(Extension ClassLoader):該類加載器負(fù)責(zé)加載JDK安裝目錄下的\jre\lib\ext的類,或者由java.ext.dirs系統(tǒng)變量指定路徑中的所有類庫,開發(fā)者也可以直接使用擴(kuò)展類加載器。
應(yīng)用程序類加載器(AppClassLoader):負(fù)責(zé)加載用戶類路徑(Classpath)所指定的類,開發(fā)者可以直接使用該類加載器,如果應(yīng)用程序中沒有定義過自己的類加載器,該類加載器為默認(rèn)的類加載器。
用戶自定義類加載器(User ClassLoader):JVM自帶的類加載器是從本地文件系統(tǒng)加載標(biāo)準(zhǔn)的java class文件,而自定義的類加載器可以做到在執(zhí)行非置信代碼之前,自動驗(yàn)證數(shù)字簽名,動態(tài)地創(chuàng)建符合用戶特定需要的定制化構(gòu)建類,從特定的場所(數(shù)據(jù)庫、網(wǎng)絡(luò)中)取得java class。
注意如上的類加載器并不是通過繼承的方式實(shí)現(xiàn)的,而是通過組合的方式實(shí)現(xiàn)的。而JAVA虛擬機(jī)的加載模式是一種委派模式,如上圖中的1-7步所示。下層的加載器能夠看到上層加載器中的類,反之則不行。類加載器可以加載類但是不能卸載類。說了一大堆,還是感覺需要拿點(diǎn)代碼說事。
首先我們先定義自己的類加載器MyClassLoader,繼承自ClassLoader,并覆蓋了父類的findClass(String name)方法,如下:
public class MyClassLoader extends ClassLoader{ private String loaderName; //類加載器名稱 private String path = ""; //加載類的路徑 private final String fileType = ".class"; public MyClassLoader(String name){ super(); //應(yīng)用類加載器為該類的父類 this.loaderName = name; } public MyClassLoader(ClassLoader parent,String name){ super(parent); this.loaderName = name; } public String getPath(){return this.path;} public void setPath(String path){this.path = path;} @Override public String toString(){return this.loaderName;} @Override public Class<?> findClass(String name) throws ClassNotFoundException{ byte[] data = loaderClassData(name); return this.defineClass(name, data, 0, data.length); } //讀取.class文件 private byte[] loaderClassData(String name){ InputStream is = null; byte[] data = null; ByteArrayOutputStream baos = new ByteArrayOutputStream(); try { is = new FileInputStream(new File(path + name + fileType)); int c = 0; while(-1 != (c = is.read())){ baos.write(c); } data = baos.toByteArray(); } catch (Exception e) { e.printStackTrace(); } finally{ try { if(is != null) is.close(); if(baos != null) baos.close(); } catch (IOException e) { e.printStackTrace(); } } return data; } }