自定义类加载器:
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];
FileInputStream fin = new FileInuptStream(file);
//一次读取class文件的全部二进制数据
Int r = fin.read(raw);
If(r!=len)
Throw new IOException(“无法读取全部文件”+r+”!=”+len);
Fin.close();
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(“ClassNotFoundException:”+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();
}
}
//如果claszz为null,表明加载失败,则抛出异常
If(clazz==null){
Thow 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.leng-1];
Sytem.arraycopy(args,1,progargs,0,progArgs.length);
CompileClassLoader cl = new CompileClassLoader();
//加载需要运行的类
Class<?> clazz = cl.loadClass(progClass);
//获取需要运行的类的主方法
Method main= clazz.getMethod(“main”,(new String[0]).getClass());
Object argsArray[] = {progargs};
Main.invoke(null,argsArray);
}
}
自定义加载器实现如下功能:
执行代码前自动验证数字签名
根据用户提供的密码解密代码,从而可以实现代码混淆器来避免反编译class文件
根据用户需求来动态的加载类
根据应用需求把其他数据以字节码的形式加载到应用中 |