---------------------- ASP.Net+Android+IOS开发、.Net培训、期待与您交流! ----------------------
类加载器:
类加载器,
作用:类加载器负责加载java类的字节码文件到java虚拟机中
过程:首先java源程序在经过编译器编译之后形成class文件,类加载器负责负责读取class文件,
并转换成java.lang.Class类的一个实例,每个这样的实例都表示一个java类
1、类加载器的作用:当JVM运作时需要使用某个类,就需要加对应的字节码文件加载到内存中,而类加载器就是负责这个工作的。如果需要多次使用该字节码文件,类加载器不会多次加载,而是直接使用内存中的字节码
2、系统默认三个类加载器:BootStrap、ExtClassLoader、AppClassLoader,类加载器也是类.
但是BootStrap特殊,它不是类,它是嵌套在JVM中的,java程序调用它会返回null
BootStrap类加载随着JVM的启动而启动,它的作用是加载其他的系统默认类加载器(ExtClassLoaderAppClassLoader)
3、如果发生了空指针异常,那么一定是某方法前的某对象为null
4、类加载器的管辖范围:
BootStrap----------------jre/lin/re.jra
ExtClassLoader-----------jre/lin/ext/*.jar
AppClassLoader-----------CLASSPATH指定的所有jar或目录
public class ClassLoaderTest {
public static void main(String[] args) {
/*获取类加载器的名称*/
//第一步:获取class类对象
Class c = ClassLoaderTest.class;
//第二步:获取该类类加载器对象(也就是获取到加载该类的类加载器)
ClassLoader cl = c.getClassLoader();
//第三步:获取该类加载器的Class对象
Class c2 = cl.getClass();
//第四步:返回该类对象表示的实体名称
String str = c2.getName();
System.out.println(str); //结果是AppClassLoader类加载器
/*获取null类加载器,也就是BootStrap,System类就是由此类加载器加载的*/
//第一步:获取class类对象
Class c3 = System.class;
//第二步:获取该类类加载器(也就是获取到加载该类的类加载器)
ClassLoader cl1 = c3.getClassLoader();
System.out.println(cl1);
委托机制:
1、当需要某个类加载器去加载指定的类时,由某个子类加载器层层向上推进到BootStrap加载器,如果BootStrap加载器无法加载,又会层层向下递推到子类加载器,如果退回到发起的类加载器还是没有办法加载的话,那么就会抛出ClassNotFoundException异常
2、好处:如果两个自定义类加载器,如果没有委托机制,他们去加载同一个类时就会在内存中产生两份相同的字节码文件,这样浪费资源,而如果有了委托机制,加载类时都会去父类加载器中查看是否能够加载,再次加载同一个类时,会直接使用内存中已经加载过的,这样节省了资源
测试委托机制:
/*测试类加载器的委托机制
* 1、注意到AppClassLoader和ExtClassLoader打印出的类名是Launcher,这说明他们都是Launcher类的内部类
* */
//第一步:获取类加载器对象
ClassLoader clo = ClassLoaderTest.class.getClassLoader();
//第二步:返回该类加载器的委托的父类加载器
while(clo!=null){
System.out.println(clo.getClass().getName());
//返回委托的父类加载器
clo = clo.getParent();
}
System.out.println(clo);
}
有一道面试题:能否自己创建java.lang.System类?
答:不能,因为即使自己创建了System类,因为加载时受委托机制的影响,父类BootStrap会加载java系统中的System,而不会加载自定义的System类
怎么解决呢?
答:可以自定义类加载器
自定义类加载器:
loadClass方法会自动调用findClass方法!
两种方式:
一,覆盖ClassLoader抽象父类中的loadClass方法, 但是这样自己要重新编写双亲委托机制,这样很麻烦
二,不用覆盖loadClass方法,而是覆盖findClass方法,这样的话当loadClass方法中调用父类加载器加载失败,就会调用到自定义的findClass方法,这样既能保证自定义的类加载器符合双亲委托机制
---------------------- ASP.Net+Android+IOS开发、.Net培训、期待与您交流! ----------------------
详细请查看:http://edu.csdn.net