---------------------- ASP.Net+Android+IO开发S、.Net培训、期待与您交流! ----------------------
类加载器
类加载器是加载类的工具,JVM会将程序中用到的类通过类加载器从硬盘上的class二进制文件加载到内存中。Java中有三种默认的主要类加载器,是父子形式的结构:BootStExtClassLoader(非Java语言编写,嵌套在虚拟机),ExtClassLoader,AppClassLoader。查看一个类的类加载器情况:java.lang.String.class.getClassLoader().getName(),获得类加载器的名称,有个特殊的是BootStrap类加载器返回的名称是null。
系统类加载器管辖范围
BootStrap:加载 JRE/lib/rt.jar
ExtClassLoader:加载JRE/ext/*.jar
AppClassLoader:加载classpath路径下的jar包或者class文件。
委托加载机制
Java中类加载器加载时会依次向上递交给父类的类加载器,由父类去加载,最终提交给BootStrap类加载器,如果BootStrap类加载器加载不了就依次递交给下一级类加载器去加载,如果连AppClassLoader类加载器也加载不了就会报异常ClassNotFoundException,这就是委托加载机制,这委托机制保证了内存中只有一份类的字节码,硬盘上的同一份class文件如果被不同的类加载器加载,在内存就有两份字节码,用这两份字节码分别创建出来的对象JVM会认为它们是不同的。我们可以自定义类加载器,如果父类加载器没找到就用自己的类加载器加载。要注意的是,一个类A中如果涉及到另外一个类B,类B用的是类A的加载器,类A则会依次递交给父类去加载。
自定义类加载器
class ClazzLoader extends ClassLoader{
//定义自己的类加载器要先继承ClassLoader成为它的子类
//初始化时传一个要被加载的类的目录
String dir;
ClazzLoader(String dir){
this.dir=dir;
}
//覆盖findClass(String name)方法,读取硬盘上的class文件存在缓冲区中
//然后把字节数组流中的数据转换成byte数组格式,用define()方法生成字节码并返回
//下面字节流有异常抛出需要捕获,这是子类的异常所以只能用try catch处理,这里暂不处理异常
Class findClass(String name) {
String fileName=dir+"\\"+name+".class";
FileInputStream fis=new FileInputStream(fileName);
ByteArrayOutputStream bos=new ByteArrayOutputStream();
int b=-1;
while((b=fis.read())!=-1){
bos.write(b);
}
fis.close();
bos.close();
byte[ ] byteArr=bos.toByteArray();
return defineClass(byteArr,0,byteArr.length);
}
}
class CLdemo{
public static void main(String [] args){
//创建自定义的类加载器,用loadClass()加载所需类文件
Class cl=new ClazzLoader("d:\\java\\itheima").loadClass("test.class");
//注意loadClass(String name) 方法里的name只能是二进制文件名,系统类加载器加载的必须是二进制文件名
//JVM会先调用系统的类加载器去加载test.class,系统类加载器加载不到才会用ClazzLoader去加载
}
}
---------------------- ASP.Net+Android+IOS开发、 .Net培训、期待与您交流! ----------------------详细请查看: http://edu.youkuaiyun.com