Java基礎之自定義類加載器
一、類加載器關(guān)系
自定義類加載器
創(chuàng)建一個類繼承ClassLoader類,同時重寫findClass方法,用于判斷當前類的class文件是否已被加載
二、基于本地class文件的自定義類加載器
本地class文件路徑
自定義類加載器:
//創(chuàng)建自定義加載器類繼承ClassLoader類 public class MyClassLoader extends ClassLoader{ // 包路徑 private String Path; // 構(gòu)造方法,用于初始化Path屬性 public MyClassLoader(String path) { this.Path = path; } // 重寫findClass方法,參數(shù)name表示要加載類的全類名(包名.類名) @Override protected Class<?> findClass(String name) throws ClassNotFoundException { System.out.println("findclass方法執(zhí)行"); // 檢查該類的class文件是否已被加載,如果已加載則返回class文件(字節(jié)碼文件)對象,如果沒有加載返回null Class<?> loadedClass = findLoadedClass(name); // 如果已加載直接返回該類的class文件(字節(jié)碼文件)對象 if (loadedClass != null){ return loadedClass; } // 字節(jié)數(shù)組,用于存儲class文件的字節(jié)流 byte[] bytes = null; try { // 獲取class文件的字節(jié)流 bytes = getBytes(name); } catch (Exception e) { e.printStackTrace(); } if (bytes != null){ // 如果字節(jié)數(shù)組不為空,則將class文件加載到JVM中 System.out.println(bytes.length); // 將class文件加載到JVM中,返回class文件對象 Class<?> aClass = this.defineClass(name, bytes, 0, bytes.length); return aClass; }else { throw new ClassNotFoundException(); } } // 獲取class文件的字節(jié)流 private byte[] getBytes(String name) throws Exception{ // 拼接class文件路徑 replace(".",File.separator) 表示將全類名中的"."替換為當前系統(tǒng)的分隔符,F(xiàn)ile.separator返回當前系統(tǒng)的分隔符 String FileUrl = Path + name.replace(".", File.separator) + ".class"; byte[] bytes; // 相當于一個緩存區(qū),動態(tài)擴容,也就是隨著寫入字節(jié)的增加自動擴容 ByteArrayOutputStream arrayOutputStream = new ByteArrayOutputStream(); File file = new File(FileUrl); // 創(chuàng)建輸入流 InputStream inputStream = new FileInputStream(file); int content; // 循環(huán)將輸入流中的所有數(shù)據(jù)寫入到緩存區(qū)中 while ((content = inputStream.read()) != -1){ arrayOutputStream.write(content); arrayOutputStream.flush(); } bytes = arrayOutputStream.toByteArray(); return bytes; } }
測試類
三、遇到的問題
在獲取class文件字節(jié)流的getBytes方法中,為什么不將輸入流中的所有數(shù)據(jù)直接寫入到bytes中,而是要先寫入到ByteArrayOutputStream中?如下:
現(xiàn)在我們嘗試將數(shù)據(jù)直接寫入到bytes中,如下:
但在運行時報錯:
Extra bytes at the end of class file com/smallsweets/OutSide
這是為什么呢?個人理解如下:
看報錯提示Extra bytes at the end of
:在文件的最后有多余的字節(jié)
查看class文件的大小
但是字節(jié)數(shù)組在初始化時指定的大小是1024,多余位置的字節(jié)是0,所以就出現(xiàn)了多余字節(jié)的情況
解決方法是:我們可以在初始化數(shù)組時將數(shù)組的大小指定為和class文件相同大小,如下:
這樣就可以解決了,雖然可以解決,但如果每次加載類時都要修改未免有些麻煩,所以這里我們直接使用ByteArrayOutputStream,因為它是動態(tài)擴容的,也就是大小是隨寫入數(shù)據(jù)的多少而動態(tài)變化的不會出現(xiàn)多余字節(jié)的情況
四、基于網(wǎng)絡(url)class文件的自定義類加載器
class文件路徑
自定義類加載器:
public class MyUrlClassLoader extends ClassLoader { private String Path; public MyUrlClassLoader(String path) { this.Path = path; } // 參數(shù)name表示全類名(包名.類名) @Override protected Class<?> findClass(String name) throws ClassNotFoundException { // 判斷該類的class文件是否已加載,已加載直接返回class文件對象,沒有加載返回null Class<?> loadedClass = this.findLoadedClass(name); if (loadedClass != null){ return loadedClass; } byte[] bytes = null; try { // 獲取網(wǎng)絡class文件的字節(jié)數(shù)組 bytes = getBytes(Path); } catch (Exception e) { e.printStackTrace(); } // 如果字節(jié)數(shù)組不為空,將class文件加載到JVM中 if (bytes != null){ // 將class文件加載到JVM中,參數(shù)(全類名,字節(jié)數(shù)組,起始位置,長度) Class<?> aClass = this.defineClass(name, bytes, 0, bytes.length); return aClass; }else { throw new ClassNotFoundException(); } } // 獲取網(wǎng)絡class文件的字節(jié)流,參數(shù)為class文件的url private byte[] getBytes(String fileUrl) throws Exception { byte[] bytes; // 創(chuàng)建url對象 URL url = new URL(fileUrl); HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection(); // 連接url httpURLConnection.connect(); // 創(chuàng)建輸入流,獲取網(wǎng)絡中class文件的字節(jié)流 InputStream inputStream = httpURLConnection.getInputStream(); // 相當于緩存區(qū),動態(tài)擴容 ByteArrayOutputStream arrayOutputStream = new ByteArrayOutputStream(); int content; // 循環(huán)將輸入流中的所有數(shù)據(jù)寫入到緩存區(qū)中 while ((content = inputStream.read()) != -1){ arrayOutputStream.write(content); arrayOutputStream.flush(); } bytes = arrayOutputStream.toByteArray(); return bytes; } }
測試類
到此這篇關(guān)于Java基礎之自定義類加載器的文章就介紹到這了,更多相關(guān)Java自定義類加載器內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
解決eclipse中maven引用不到已經(jīng)存在maven中jar包的問題
這篇文章主要介紹了解決eclipse中maven引用不到已經(jīng)存在maven中jar包的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-10-10Spring Boot中使用Server-Sent Events (SSE) 實
Server-Sent Events (SSE) 是HTML5引入的一種輕量級的服務器向瀏覽器客戶端單向推送實時數(shù)據(jù)的技術(shù),本文主要介紹了Spring Boot中使用Server-Sent Events (SSE) 實現(xiàn)實時數(shù)據(jù)推送教程,具有一定的參考價值,感興趣的可以了解一下2024-03-03BiConsumer接口中的方法andThen?accept使用詳解
這篇文章主要為大家介紹了BiConsumer接口中的方法andThen?accept使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-07-07Java實現(xiàn)遠程控制技術(shù)完整源代碼分享
這篇文章主要為大家詳細介紹了Java實現(xiàn)遠程控制技術(shù)完整源代碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下2016-08-08