小編給大家分享一下Java中自定義類加載器和動態(tài)加載的示例分析,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!
創(chuàng)新互聯(lián)公司從2013年成立,是專業(yè)互聯(lián)網(wǎng)技術(shù)服務(wù)公司,擁有項目成都網(wǎng)站制作、成都網(wǎng)站設(shè)計網(wǎng)站策劃,項目實施與項目整合能力。我們以讓每一個夢想脫穎而出為使命,1280元北川羌族做網(wǎng)站,已為上家服務(wù),為北川羌族各地企業(yè)和個人服務(wù),聯(lián)系電話:028-86922220
我們需要一個自定義的類加載器,完成任何路徑包括網(wǎng)絡(luò)的文件加載,這個是取得 java 字節(jié)碼文件,也就是編譯后的 class 文件,他可能在世界的某個角落。
實現(xiàn)自定義的類加載器首先是繼承ClassLoader
這個類,來看下構(gòu)造方法代碼
public class MyClassLoad extends ClassLoader { private String rootPath; public MyClassLoad(String rootPath) { this.rootPath = rootPath; } }
構(gòu)造方法,僅僅是把路徑傳入,也就是 class 文件的文件夾,不包括包名稱的路徑;
接下來重寫findClass
方法;
/** * 根據(jù)name來尋找該類 * */ @Override protected Class> findClass(String name) throws ClassNotFoundException { Class> c = findLoadedClass(name); if (c == null) { // 內(nèi)存堆中還沒加載該類 c = findMyClass(name); // 自己實現(xiàn)加載類 } return c; }
首先在內(nèi)存堆里面查找,沒有加載的話就到自己實現(xiàn),看下findMyClass
方法
/** * 加載該類 * * @param name * @return */ private Class> findMyClass(String name) { try { byte[] bytes = getData(name); return this.defineClass(null, bytes, 0, bytes.length); // 調(diào)用父類方法,生成具體類 } catch (Exception e) { e.printStackTrace(); } return null; }
該方法根據(jù)字節(jié)數(shù)組返回Class
類,根據(jù) class 文件獲取字節(jié)數(shù)組可以使用Apache 文件操作相關(guān)輔助類,這里使用原生 jdk 實現(xiàn);
private byte[] getData(String className) { String path = rootPath + File.separatorChar + className.replace('.', File.separatorChar) + ".class"; InputStream is = null; try { is = new FileInputStream(path); ByteArrayOutputStream stream = new ByteArrayOutputStream(); byte[] buffer = new byte[2048]; int num = 0; while ((num = is.read(buffer)) != -1) { stream.write(buffer, 0, num); } return stream.toByteArray(); } catch (IOException e) { e.printStackTrace(); } finally { if (is != null) { try { is.close(); } catch (IOException e) { e.printStackTrace(); } } } return null; }
這個簡單的自定義類加載器就差不多了,如果需要實現(xiàn)自己加密解密的可以在字節(jié)數(shù)組里面進(jìn)行折騰,這里不再深入,我們的目標(biāo)是熱加載一段 java代碼,可能的解決方法是,構(gòu)建一個 java 模板,里面內(nèi)置一些方法,外界可以增加一些新的方法,也可以調(diào)用內(nèi)置方法。
好!開始一個簡單的,把一段代碼加載到內(nèi)存并且執(zhí)行吧。
import java.io.File;import java.io.FileWriter;import javax.tools.JavaCompiler;import javax.tools.JavaCompiler.CompilationTask;import classload.MyClassLoad;import javax.tools.JavaFileObject;import javax.tools.StandardJavaFileManager;import javax.tools.ToolProvider;public class LoadJava { public static final String javaCode = "package classload;public class HelloWorld2 {public HelloWorld2() {System.out.println(\"Hello World\");}}"; public static void runJavaCode() throws Exception { // 把 java String 存儲到文件 String fileName = "/Users/XXXXXXX/Documents/demo/java/classload/HelloWorld2.java"; File file = new File(fileName); FileWriter fw = new FileWriter(file); fw.write(javaCode); fw.flush(); fw.close(); // JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler(); StandardJavaFileManager standardFileManager = javaCompiler.getStandardFileManager(null, null, null); Iterable extends JavaFileObject> iterable = standardFileManager.getJavaFileObjects(fileName); // 執(zhí)行編譯任務(wù) CompilationTask task = javaCompiler.getTask(null, standardFileManager, null, null, null, iterable); task.call(); standardFileManager.close(); // 把編譯后的 class 文件加載到內(nèi)存 ClassLoader pcl = new MyClassLoad("/Users/XXXXXXX/Documents/demo/java/"); Class c = pcl.loadClass("classload.HelloWorld2"); System.out.println(c.newInstance()); } public static void main(String[] args) { try { LoadJava.runJavaCode(); } catch (Exception e) { e.printStackTrace(); } } }
以上是“Java中自定義類加載器和動態(tài)加載的示例分析”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對大家有所幫助,如果還想學(xué)習(xí)更多知識,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道!