类加载器:
加载类的工具,java程序里用到一个类,比如:System,JVM首先把类的字节码加载到内存中,原始信息放在classpath的原始路径下。把.class文件加载进来进行处理。
系统默认3个主要类加载器,每个类负责加载特定位置的类
类加载器也是Java类,BootStrap不是Java类
------------------------------------------------------------------------------
类加载器之间的父子关系和管辖范围图
BootStrap——————JRE/lib/rt.jar
|
ExClassLoader———JRE/lib/ext/*.jar
|
AppClassLoader——CLASSPATH指定的所有jar或目录
类加载器的委托机制
首先,当前线程的类加载器去加载线程中的第一个类
如果类A中引用了类B,JVM将使用加载类A的类加载器来加载类B
还可以直接调用ClassLoader.loadClass()方法来指定某个类加载器去加载某个类
每个类加载器加载类时,又先委托给其上级类加载器
当所有祖宗类加载器没有加载到类,回到发起者类加载器,还加载不了,则抛出ClassNotFoundException
不是再去找发起者类加载器的儿子,因为没有geiChild方法,即使有,那么多二个儿子,找哪一个呢?
eg:能不能写一个类叫java.lang.System,为了不让我们写System类,类加载器采用委托机制,这样可以保证爸爸们优先,
也就是总是使用爸爸们能找到的类,这样总是使用java系统提供的System
通常不可以,原因就在于委托机制,但是可以自己写一个类加载器。不能委托给上级
-------------------------------------------------------------------------------------------------------------------------
自定义类加载器原理
覆盖findClass
-------------------------------------------------------------------------------------------------------------------------
类加载器的高级问题
编写一个能打印出自己的类加载器名称和当前类加载器的父子结构关系链的MyServlet
//servlet这个对象
ClassLoader loader = this.getClass().getClassLoader();
while(loader!=null){
out.println(loader.getClass().getName());
loader = loader.getParent();
}
正常发布后,看到打印结果为webAppClassloader
把MyServlet.class文件打Jar包放到ext目录中,重启tomcat发现找不到httpServlet的错误
把servlet.jar也放到ext目录中,问题解决了,打印的结果是ExtclassLoader
父类加载器加载的类无法饮用只能被子级类加载器加载的类
原理图: