小編給大家分享一下Java中自定義類加載器和動態加載的示例分析,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!
我們需要一個自定義的類加載器,完成任何路徑包括網絡的文件加載,這個是取得 java 字節碼文件,也就是編譯后的 class 文件,他可能在世界的某個角落。
實現自定義的類加載器首先是繼承ClassLoader這個類,來看下構造方法代碼
public class MyClassLoad extends ClassLoader { private String rootPath; public MyClassLoad(String rootPath) { this.rootPath = rootPath;
}
}構造方法,僅僅是把路徑傳入,也就是 class 文件的文件夾,不包括包名稱的路徑;
接下來重寫findClass方法;
/**
* 根據name來尋找該類
*
*/
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
Class<?> c = findLoadedClass(name); if (c == null) { // 內存堆中還沒加載該類
c = findMyClass(name); // 自己實現加載類
} return c;
}首先在內存堆里面查找,沒有加載的話就到自己實現,看下findMyClass方法
/**
* 加載該類
*
* @param name
* @return
*/
private Class<?> findMyClass(String name) { try { byte[] bytes = getData(name); return this.defineClass(null, bytes, 0, bytes.length); // 調用父類方法,生成具體類
} catch (Exception e) {
e.printStackTrace();
} return null;
}該方法根據字節數組返回Class類,根據 class 文件獲取字節數組可以使用Apache 文件操作相關輔助類,這里使用原生 jdk 實現;
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;
}這個簡單的自定義類加載器就差不多了,如果需要實現自己加密解密的可以在字節數組里面進行折騰,這里不再深入,我們的目標是熱加載一段 java代碼,可能的解決方法是,構建一個 java 模板,里面內置一些方法,外界可以增加一些新的方法,也可以調用內置方法。
好!開始一個簡單的,把一段代碼加載到內存并且執行吧。
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); // 執行編譯任務
CompilationTask task = javaCompiler.getTask(null, standardFileManager, null, null, null, iterable);
task.call();
standardFileManager.close(); // 把編譯后的 class 文件加載到內存
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中自定義類加載器和動態加載的示例分析”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。