java import自定义类_Java实现的自定义类加载器示例
本文實例講述了Java實現的自定義類加載器。分享給大家供大家參考,具體如下:
一 點睛
1 ClassLoader類有如下兩個關鍵方法:
loadClass(String name, boolean resolve):該方法為ClassLoader的入口點,根據指定的二進制名稱來加載類,系統就是調用ClassLoader的該方法來獲取指定類對應的Class對象。
findClass(String name):根據二進制名稱來查找類。
如果需要實現自定義的ClassLoader,可以通過重寫以上兩個方法來實現,當然我們推薦重寫findClass()方法,而不是重寫loadClass()方法。
2 自定義類加載器常用功能
執行代碼前自動驗證數字簽名。
根據用戶提供的密碼解密代碼,從而可以實現代碼混淆器來避免反編譯class文件。
根據用戶需求來動態地加載類。
根據應用需求把其他數據以字節碼的形式加載到應用中。
二 實戰
1 CompileClassLoader.java
import java.io.*;
import java.lang.reflect.*;
public class CompileClassLoader extends ClassLoader
{
// 讀取一個文件的內容
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文件的全部二進制數據
int r = fin.read(raw);
if(r != len)
throw new IOException("無法讀取全部文件:"
+ r + " != " + len);
return raw;
}
}
// 定義編譯指定Java文件的方法
private boolean compile(String javaFile)
throws IOException
{
System.out.println("CompileClassLoader:正在編譯 "
+ javaFile + "...");
// 調用系統的javac命令
Process p = Runtime.getRuntime().exec("javac " + javaFile);
try
{
// 其他線程都等待這個線程完成
p.waitFor();
}
catch(InterruptedException ie)
{
System.out.println(ie);
}
// 獲取javac線程的退出值
int ret = p.exitValue();
// 返回編譯是否成功
return ret == 0;
}
// 重寫ClassLoader的findClass方法
protected Class> findClass(String name)
throws ClassNotFoundException
{
Class clazz = null;
// 將包路徑中的點(.)替換成斜線(/)。
String fileStub = name.replace("." , "/");
String javaFilename = fileStub + ".java";
String classFilename = fileStub + ".class";
File javaFile = new File(javaFilename);
File classFile = new File(classFilename);
// 當指定Java源文件存在,且class文件不存在、或者Java源文件
// 的修改時間比class文件修改時間更晚,重新編譯
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文件存在,系統負責將該文件轉換成Class對象
if (classFile.exists())
{
try
{
// 將class文件的二進制數據讀入數組
byte[] raw = getBytes(classFilename);
// 調用ClassLoader的defineClass方法將二進制數據轉換成Class對象
clazz = defineClass(name,raw,0,raw.length);
}
catch(IOException ie)
{
ie.printStackTrace();
}
}
// 如果clazz為null,表明加載失敗,則拋出異常
if(clazz == null)
{
throw new ClassNotFoundException(name);
}
return clazz;
}
// 定義一個主方法
public static void main(String[] args) throws Exception
{
// 如果運行該程序時沒有參數,即沒有目標類
if (args.length < 1)
{
System.out.println("缺少目標類,請按如下格式運行Java源文件:");
System.out.println("java CompileClassLoader ClassName");
}
// 第一個參數是需要運行的類
String progClass = args[0];
// 剩下的參數將作為運行目標類時的參數,
// 將這些參數復制到一個新數組中
String[] progArgs = new String[args.length-1];
System.arraycopy(args , 1 , progArgs
, 0 , progArgs.length);
CompileClassLoader ccl = new CompileClassLoader();
// 加載需要運行的類
Class> clazz = ccl.loadClass(progClass);
// 獲取需要運行的類的主方法
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("運行Hello的參數:" + arg);
}
}
}
3 運行
E:\Java\瘋狂java講義\codes\18\18.2>java CompileClassLoader Hello 自定義加載器
CompileClassLoader:正在編譯 Hello.java...
運行Hello的參數:自定義加載器
希望本文所述對大家java程序設計有所幫助。
總結
以上是生活随笔為你收集整理的java import自定义类_Java实现的自定义类加载器示例的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java excel data 导入数据
- 下一篇: java美元兑换,(Java实现) 美元