這篇文章給大家分享的是有關(guān)java實(shí)現(xiàn)自定義類加載器的方法的內(nèi)容。小編覺得挺實(shí)用的,因此分享給大家做個(gè)參考。一起跟隨小編過來看看吧。
創(chuàng)新互聯(lián)公司主要從事成都網(wǎng)站制作、做網(wǎng)站、外貿(mào)營銷網(wǎng)站建設(shè)、網(wǎng)頁設(shè)計(jì)、企業(yè)做網(wǎng)站、公司建網(wǎng)站等業(yè)務(wù)。立足成都服務(wù)仲巴,十余年網(wǎng)站建設(shè)經(jīng)驗(yàn),價(jià)格優(yōu)惠、服務(wù)專業(yè),歡迎來電咨詢建站服務(wù):18980820575各類加載器雖然以父子相稱,但是沒有繼承關(guān)系
點(diǎn)入ClassLoader的源碼查看樣例:
** class NetworkClassLoader extends ClassLoader { * String host; * int port; * * public Class findClass(String name) { * byte[] b = loadClassData(name); * return defineClass(name, b, 0, b.length); * } * * private byte[] loadClassData(String name) { * // load the class data from the connection * . . . * } * } *
只需繼承CalssLoader,重寫 findClass方法即可:
package reflect; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.List; public class MyClassLoader extends ClassLoader{ // 用于保存加載的文件的大小 private int classSize; // 新增的類加載路徑 private static Listpaths = new ArrayList<>(); static { paths.add("D:\\Users\\jeff.chan\\Desktop\\"); } // 默認(rèn)會(huì)將app類加載器做為該類加載器的父加載器 public MyClassLoader() { } public MyClassLoader(ClassLoader parent) { super(parent); } @Override protected Class> findClass(String name) throws ClassNotFoundException { byte[] b = loadBinaryData(name); // 打印執(zhí)行標(biāo)記 System.out.println("use custom classloader..."); return defineClass(name, b,0, classSize); } public byte[] loadBinaryData(String name) throws ClassNotFoundException{ String pathName = name.replaceAll("\\.", "/"); File file = null; for (String path : paths) { file = new File(path+pathName+".class"); if(file.exists() && file.isFile()){ break; } } if(file==null || !file.isFile()){ throw new ClassNotFoundException(); } // 讀取文件的二進(jìn)制信息 try (InputStream in = new FileInputStream(file)){ // 一般這個(gè)大小夠了,這里是為了方便讀取 // 文件的內(nèi)容,所以一次性讀入,并且將大小返回 // 用于defineClass byte[] b = new byte[1024 * 1024 * 10]; classSize = in.read(b); return b; }catch (IOException ioException){ ; } return null; } }
這里加入了一個(gè)MyClassLoader自定義類加載器,掃描的路徑為:
D:\\Users\\jeff.chan\\Desktop\\
那么新加入的類加載器就和app類加載器,擴(kuò)展類加載器,啟動(dòng)類加載器一起起作用。
測(cè)試用例:
package reflect; public class Person { private String name; private String age; public Person() { } public Person(String name, String age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAge() { return age; } public void setAge(String age) { this.age = age; } @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age='" + age + '\'' + '}'; } }
客戶端:
package reflect; public class Client { public static void main(String[] args) throws Exception { MyClassLoader classLoader = new MyClassLoader(); Class> aClass = classLoader.loadClass("reflect.Person"); System.out.println(aClass); System.out.println(aClass.getClassLoader()); } }
時(shí)直接運(yùn)行代碼:那么會(huì)輸出
class reflect.Person
sun.misc.Launcher$AppClassLoader@18b4aac2
發(fā)現(xiàn)自己的類加載器根本不起作用。其實(shí)是因?yàn)殡p親委托機(jī)制:
1、MyClassLoader 查看是否已經(jīng)加載 -》 2、App類加載查看是否已經(jīng)加載 -》3、 擴(kuò)展類加載器查看是否已經(jīng)加載
-》 4、啟動(dòng)類加載器查看是否已經(jīng)加載,沒有加載就嘗試加載 -》 5、擴(kuò)展類嘗試加載 -》 6、app類加載嘗試加載 -》 7、MyClassLoader嘗試加載 -》 8、拋出找不到類的異常
上述的流程中,第6步會(huì)找到對(duì)應(yīng)的類,所以就直接返回了,根本沒有給MyClassLoader機(jī)會(huì)加載,所以才沒有調(diào)用自定義的類加載器MyClassLoader。
如果想要加載的話,那么就到編譯生成的Person.class移動(dòng)到桌面reflect/Person.class下,執(zhí)行結(jié)果:
use custom classloader...
class reflect.Person
reflect.MyClassLoader@135fbaa4
結(jié)果發(fā)現(xiàn),自定義的類加載起作用了,其實(shí)就是上述的流程中的第7步,找到了相應(yīng)的類的二進(jìn)制文件,加載了進(jìn)來。
感謝各位的閱讀!關(guān)于java實(shí)現(xiàn)自定義類加載器的方法就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,讓大家可以學(xué)到更多知識(shí)。如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到吧!