您好,登錄后才能下訂單哦!
這篇文章給大家分享的是有關(guān)java實現(xiàn)自定義類加載器的方法的內(nèi)容。小編覺得挺實用的,因此分享給大家做個參考。一起跟隨小編過來看看吧。
各類加載器雖然以父子相稱,但是沒有繼承關(guān)系
點入ClassLoader的源碼查看樣例:
* <blockquote><pre> * 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 * . . . * } * } * </pre></blockquote>
只需繼承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 List<String> paths = new ArrayList<>(); static { paths.add("D:\\Users\\jeff.chan\\Desktop\\"); } // 默認會將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(); } // 讀取文件的二進制信息 try (InputStream in = new FileInputStream(file)){ // 一般這個大小夠了,這里是為了方便讀取 // 文件的內(nèi)容,所以一次性讀入,并且將大小返回 // 用于defineClass byte[] b = new byte[1024 * 1024 * 10]; classSize = in.read(b); return b; }catch (IOException ioException){ ; } return null; } }
這里加入了一個MyClassLoader自定義類加載器,掃描的路徑為:
D:\\Users\\jeff.chan\\Desktop\\
那么新加入的類加載器就和app類加載器,擴展類加載器,啟動類加載器一起起作用。
測試用例:
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()); } }
時直接運行代碼:那么會輸出
class reflect.Person
sun.misc.Launcher$AppClassLoader@18b4aac2
發(fā)現(xiàn)自己的類加載器根本不起作用。其實是因為雙親委托機制:
1、MyClassLoader 查看是否已經(jīng)加載 -》 2、App類加載查看是否已經(jīng)加載 -》3、 擴展類加載器查看是否已經(jīng)加載
-》 4、啟動類加載器查看是否已經(jīng)加載,沒有加載就嘗試加載 -》 5、擴展類嘗試加載 -》 6、app類加載嘗試加載 -》 7、MyClassLoader嘗試加載 -》 8、拋出找不到類的異常
上述的流程中,第6步會找到對應(yīng)的類,所以就直接返回了,根本沒有給MyClassLoader機會加載,所以才沒有調(diào)用自定義的類加載器MyClassLoader。
如果想要加載的話,那么就到編譯生成的Person.class移動到桌面reflect/Person.class下,執(zhí)行結(jié)果:
use custom classloader...
class reflect.Person
reflect.MyClassLoader@135fbaa4
結(jié)果發(fā)現(xiàn),自定義的類加載起作用了,其實就是上述的流程中的第7步,找到了相應(yīng)的類的二進制文件,加載了進來。
感謝各位的閱讀!關(guān)于java實現(xiàn)自定義類加載器的方法就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,讓大家可以學(xué)到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。