您好,登錄后才能下訂單哦!
本篇文章給大家分享的是有關(guān)如何在Java中自定義一個(gè)類加載器示例,小編覺(jué)得挺實(shí)用的,因此分享給大家學(xué)習(xí),希望大家閱讀完這篇文章后可以有所收獲,話不多說(shuō),跟著小編一起來(lái)看看吧。
1 ClassLoader類有如下兩個(gè)關(guān)鍵方法:
loadClass(String name, boolean resolve):該方法為ClassLoader的入口點(diǎn),根據(jù)指定的二進(jìn)制名稱來(lái)加載類,系統(tǒng)就是調(diào)用ClassLoader的該方法來(lái)獲取指定類對(duì)應(yīng)的Class對(duì)象。
findClass(String name):根據(jù)二進(jìn)制名稱來(lái)查找類。
如果需要實(shí)現(xiàn)自定義的ClassLoader,可以通過(guò)重寫(xiě)以上兩個(gè)方法來(lái)實(shí)現(xiàn),當(dāng)然我們推薦重寫(xiě)findClass()方法,而不是重寫(xiě)loadClass()方法。
2 自定義類加載器常用功能
執(zhí)行代碼前自動(dòng)驗(yàn)證數(shù)字簽名。
根據(jù)用戶提供的密碼解密代碼,從而可以實(shí)現(xiàn)代碼混淆器來(lái)避免反編譯class文件。
根據(jù)用戶需求來(lái)動(dòng)態(tài)地加載類。
根據(jù)應(yīng)用需求把其他數(shù)據(jù)以字節(jié)碼的形式加載到應(yīng)用中。
二 實(shí)戰(zhàn)
1 CompileClassLoader.java
import java.io.*; import java.lang.reflect.*; public class CompileClassLoader extends ClassLoader { // 讀取一個(gè)文件的內(nèi)容 private byte[] getBytes(String filename) throws IOException { File file = new File(filename); long len = file.length(); byte[] raw = new byte[(int)len]; try( FileInputStream fin = new FileInputStream(file)) { // 一次讀取class文件的全部二進(jìn)制數(shù)據(jù) int r = fin.read(raw); if(r != len) throw new IOException("無(wú)法讀取全部文件:" + r + " != " + len); return raw; } } // 定義編譯指定Java文件的方法 private boolean compile(String javaFile) throws IOException { System.out.println("CompileClassLoader:正在編譯 " + javaFile + "..."); // 調(diào)用系統(tǒng)的javac命令 Process p = Runtime.getRuntime().exec("javac " + javaFile); try { // 其他線程都等待這個(gè)線程完成 p.waitFor(); } catch(InterruptedException ie) { System.out.println(ie); } // 獲取javac線程的退出值 int ret = p.exitValue(); // 返回編譯是否成功 return ret == 0; } // 重寫(xiě)ClassLoader的findClass方法 protected Class<?> findClass(String name) throws ClassNotFoundException { Class clazz = null; // 將包路徑中的點(diǎn)(.)替換成斜線(/)。 String fileStub = name.replace("." , "/"); String javaFilename = fileStub + ".java"; String classFilename = fileStub + ".class"; File javaFile = new File(javaFilename); File classFile = new File(classFilename); // 當(dāng)指定Java源文件存在,且class文件不存在、或者Java源文件 // 的修改時(shí)間比class文件修改時(shí)間更晚,重新編譯 if(javaFile.exists() && (!classFile.exists() || javaFile.lastModified() > classFile.lastModified())) { try { // 如果編譯失敗,或者該Class文件不存在 if(!compile(javaFilename) || !classFile.exists()) { throw new ClassNotFoundException( "ClassNotFoundExcetpion:" + javaFilename); } } catch (IOException ex) { ex.printStackTrace(); } } // 如果class文件存在,系統(tǒng)負(fù)責(zé)將該文件轉(zhuǎn)換成Class對(duì)象 if (classFile.exists()) { try { // 將class文件的二進(jìn)制數(shù)據(jù)讀入數(shù)組 byte[] raw = getBytes(classFilename); // 調(diào)用ClassLoader的defineClass方法將二進(jìn)制數(shù)據(jù)轉(zhuǎn)換成Class對(duì)象 clazz = defineClass(name,raw,0,raw.length); } catch(IOException ie) { ie.printStackTrace(); } } // 如果clazz為null,表明加載失敗,則拋出異常 if(clazz == null) { throw new ClassNotFoundException(name); } return clazz; } // 定義一個(gè)主方法 public static void main(String[] args) throws Exception { // 如果運(yùn)行該程序時(shí)沒(méi)有參數(shù),即沒(méi)有目標(biāo)類 if (args.length < 1) { System.out.println("缺少目標(biāo)類,請(qǐng)按如下格式運(yùn)行Java源文件:"); System.out.println("java CompileClassLoader ClassName"); } // 第一個(gè)參數(shù)是需要運(yùn)行的類 String progClass = args[0]; // 剩下的參數(shù)將作為運(yùn)行目標(biāo)類時(shí)的參數(shù), // 將這些參數(shù)復(fù)制到一個(gè)新數(shù)組中 String[] progArgs = new String[args.length-1]; System.arraycopy(args , 1 , progArgs , 0 , progArgs.length); CompileClassLoader ccl = new CompileClassLoader(); // 加載需要運(yùn)行的類 Class<?> clazz = ccl.loadClass(progClass); // 獲取需要運(yùn)行的類的主方法 Method main = clazz.getMethod("main" , (new String[0]).getClass()); Object[] argsArray = {progArgs}; main.invoke(null,argsArray); } }
2 Hello.java
public class Hello { public static void main(String[] args) { for (String arg : args) { System.out.println("運(yùn)行Hello的參數(shù):" + arg); } } }
3 運(yùn)行
E:\Java\瘋狂java講義\codes\18\18.2>java CompileClassLoader Hello 自定義加載器
CompileClassLoader:正在編譯 Hello.java...
運(yùn)行Hello的參數(shù):自定義加載器
以上就是如何在Java中自定義一個(gè)類加載器示例,小編相信有部分知識(shí)點(diǎn)可能是我們?nèi)粘9ぷ鲿?huì)見(jiàn)到或用到的。希望你能通過(guò)這篇文章學(xué)到更多知識(shí)。更多詳情敬請(qǐng)關(guān)注億速云行業(yè)資訊頻道。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。