java的加载器分为三类
引导加载器 C编写
扩展加载器
应用程序加载器
加载的过程 是从上到下的顺序。跟windows的消息钩子的执行方向相反。
之前CC++写过pe文件加载 非常麻烦,按照pe格式分配内存加载到程序空间
java提供了自定义加载器的机制 还是比较方便的,
总体流程:继承ClassLoader—-看看有没有加载过该类—-没有加载过看看父类能不能加载—-父类不能加载,自己去加载—-自己加载的流程—-获得类文件的byte[]—-调用父类接口defineClass得到Class对象
贴代码
自定义从文件加载类
package top.demo.load;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
public class FileLoad extends ClassLoader{
public String rootPath;
//F:
public FileLoad(String rootPath) {
super();
this.rootPath=rootPath;
}
//className top.demo.load.Test
public Class<?> loadFileClass(String className) throws Exception {
Class<?>cl=null;
try {
cl=findClass(className);
} catch (ClassNotFoundException e) {
//e.printStackTrace();
System.out.println("没有加载过该类");
}
if(cl!=null)
return cl;
//如果该类没有被加载 交由父类加载
try {
cl=super.loadClass(className);
} catch (ClassNotFoundException e) {
//e.printStackTrace();
System.out.println("父类不能加载该类");
}
if(cl!=null)
return cl;
//如果父类不能加载,那么我们自己加载
StringBuilder realPath=new StringBuilder();
realPath.append(rootPath);
realPath.append("/");
realPath.append(className.replace(".", "/"));
realPath.append(".class");
File file=new File(realPath.toString());
if(!file.exists()) {
throw new Exception("没有这个类文件存在");
}
byte[] classInfo=null;
classInfo=getClassFileInfo(file);
if(classInfo==null) {
throw new Exception("读取类文件可能出错");
}
cl=defineClass(className,classInfo, 0, classInfo.length);
if(cl==null)
throw new Exception("自定义加载器出错");
return cl;
}
private byte[] getClassFileInfo(File file) {
byte[] classInfo=new byte[(int) file.length()];
FileInputStream fileIn=null;
try {
int len=0;
fileIn=new FileInputStream(file);
try {
while(-1!=(len=fileIn.read(classInfo))) {
}
} catch (IOException e) {
e.printStackTrace();
classInfo=null;
try {
fileIn.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
classInfo=null;
}finally {
try {
fileIn.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return classInfo;
}
}
定义需要加载的类 并且编译成class文件放在 F:\top\demo\load下类名为Test
定义测试加载类
package top.demo.load;
public class TestLoad {
public static void main(String argv[])
{
FileLoad load=new FileLoad("F:");
Class<?> cl=null;
try {
cl=load.loadFileClass("top.demo.load.Test");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(cl!=null ? "成功加载":"加载失败");
}
}
输出结果
没有加载过该类
父类不能加载该类
成功加载