1.什么是类加载器?
加载类的工具。
2.JVM中默认的三个类加载器是什么以及它们的关系?
(1)JVM中默认的三个类加载器是BootStrap(爷爷),ExtClassLoader(儿子),AppClassLoader(孙子);
(2)BootStrap是C++写的类加载器,它存在于JVM内,负责加载其他类(包括用java写的类加载,如ExtClassLoader,AppClassLoader)
3.如何获取某个类的类加载器的名称?
ClassLoaderTest.class.getClassLoader().getClass().getName();
小插曲:
(1)System.class.getClassLoader()的结果是null,证明它的类加载器是BootStrap,因为它不是一个java类;
4.三个类加载器各自的加载的类范围:
BootStrap-->JRE/lib/rt.jar;
ExtClassLoader-->JRE/lib/ext/*.jar(我们自己写的类可以手动或者使用myeclipse放到此包下);
AppClassLoader(SystemclassLoader)--->CLASSPATH指定的所有jar或目录
5.如何写自己的类加载器?
写一个类继承ClassLoader,然后使用构造函数指定父类加载器,把此类加载器挂到父类加载器上;
6.委托机制
当类加载器要加载类的时候先自己不加载而是交给上级,看上级能不能找到,上级找不到再自己找,找不到就报错。如AppClassLoder加载类的时候先会交给ExtClassLoder,ExtClassLoder再交给BootStrap,BootStrap找到则加载(如果之前已经加载了那么就不会再加载),找不到则ExtClassLoder会找(如果之前已经加载了那么就不会再加载),找到加载,找不到再交给AppClassLoder(如果之前已经加载了那么就不会再加载),找不到报ClassNotFoundException的错误。
虽然这样的做法有些繁琐,但是可以集中管理,保证内存中一个类只有一份字节码。
小插曲:
下面的内容摘自其它地方(标志M是我自己加的内容)
“ 当Java虚拟机要加载一个类时,到底派出哪个类加载器去加载呢?
当Java虚拟机要加载一个类时首先使用当前线程的类加载器去加载线程中的第一个类。(M可以使用Thread获取当前类加载器和设置类加载器),如果类A中引用了类B,Java虚拟机将使用加载类A的类装载器来加载类B。 还可以直接调用ClassLoader.loadClass()方法来指定某个类加载器去加载某个类。”
7.可不可以自己写个System类?
通常情况下不可以,因为父类委托机制会让JVM加载java中的System,而我们自己的System不会被加载到;但是我们可以写个类加载器来加载我们自己写的System,但是自己写的类加载器要避开父类委托机制。