java默认的类加载机制是委派机制,委派过程如下:
- 从缓存中加载
- 如果缓存中没有,则从父类加载器中加载。
- 如果父类加载器中的没有,则从当前加载器加载
- 如果没有,则抛出异常
类加载器只能加载在自己的指定目录下的二进制类流。
每个类加载器都有自己的命名空间,但加载到同一片内存区域。
双亲委派机制
需求:一个限定名的类,只会被一个类加载器加载,是唯一的。越重要的越由父亲加载器加载。
UserClassLoader加载一个类,先会委派给bootstrap加载,如果检测到类已加载过,就结束,如果二进制类流不在<JAVA_HOME>/lib目录下,就委派给extensionclassLoader,查看<JAVA_HOME>/lib/ext是否存在这个类的流,如果不存在再使用ApplicationClassLoader,如果还不在classpath,则使用UserClassLoader加载。
一个限定名的类只会被一个类加载器加载,它是唯一的。
除了BootstrapClassLoader,其他类加载器都是使用ClassLoader的defineClass()方法,加载类的方式是相同的。
破坏双亲委派模型的实例
- jdbc数据库对jdk的接口的实现
jdk类的jdbc接口是由bootstrap加载的,而其jdbc接口实现是由application加载的,是bootstrap对application的委派加载。 - 热部署:自由的类加载
- Tomcat的web应用类加载器
当加载类时,除了JVM基础类库外,它首先会通过当前类加载器加载,然后再委派。
具体来说:
- 从缓存加载
- 如果没有,使用Bootstrap类加载器加载
- 如果没有使用当前加载器加载
- 如果没有,则委派父类加载器