1,类加载器构成
Bootstrap(启动类加载器 $JAVA_HOME/lib)---extension(ExtClassLoader扩展类加载器$JAVA_HOME/lib/ext)---system(AppClassLoader系统类加载器Classpath)
2,加载机制
双亲委派机制,某个特定的类加载器接受到加载请求时,首先将加载请求委托给父类加载器,一次递归,父类加载器可以完成加载任务,则成功返回,只有父类无法完成加载时,才自己去加载,jvm默认的双亲委派机制通过ClassLoader的loadClass方法来实现的。方法如下
注意:扩展类加载器的父加载器为为NUL,引导类加载器涉及到虚拟机本地实现细节,开发者无法直接获取到启动类加载器的引用
如何实现我们的自定义类加载器呢?
实现自定义加载器其它很简单。只要实现ClassLoader的findClass()方法就行了。
大概如下:
当自定义类加载器加载的类有继承相应的类或实现相应接口的话,必须把相应的父类或接口拷贝到同一路径。因为类加载器在加载子类时,会同时加载父类。
关于类的转型问题:
由于类加载器是相互隔离的,当classLoaderA加载了A类,classLoaderB也加载了A类。这个类对象是不能互相转型的。会报ClassCastException异常。
假如自定义类加载器加载A类时,而A类又实现了接口B时,我们是可以将A类的实例转成B接口的。原因是类加载器在加载A类时,会同时加载A类的所有父类(包括接口).
JAVA类加载器采用了委托模式。当一个类对象己经被加载了,就不会在去加载该类。还是直接返回。那么如何重新加载这个类呢?
实现自定义的类加载器,当类加载完成后。调用相应方法,然后在去掉相应类加载器的引用。这样类不会在存在类加载器中了。
比如:classLoaderA=null(去掉A加载器的引用)
Bootstrap(启动类加载器 $JAVA_HOME/lib)---extension(ExtClassLoader扩展类加载器$JAVA_HOME/lib/ext)---system(AppClassLoader系统类加载器Classpath)
2,加载机制
双亲委派机制,某个特定的类加载器接受到加载请求时,首先将加载请求委托给父类加载器,一次递归,父类加载器可以完成加载任务,则成功返回,只有父类无法完成加载时,才自己去加载,jvm默认的双亲委派机制通过ClassLoader的loadClass方法来实现的。方法如下
// 首先判断该类型是否已经被加载
Class c = findLoadedClass(name);
if (c == null) {
//如果没有被加载,就委托给父类加载或者委派给启动类加载器加载
try {
if (parent != null) {
//如果存在父类加载器,就委派给父类加载器加载
c = parent.loadClass(name, false);
} else {
//如果不存在父类加载器,就检查是否是由启动类加载器加载的类,通过调用本地方法native Class findBootstrapClass(String name)
c = findBootstrapClass0(name);
}
} catch (ClassNotFoundException e) {
// 如果父类加载器和启动类加载器都不能完成加载任务,才调用自身的加载功能
c = findClass(name);
}
}
注意:扩展类加载器的父加载器为为NUL,引导类加载器涉及到虚拟机本地实现细节,开发者无法直接获取到启动类加载器的引用
如何实现我们的自定义类加载器呢?
实现自定义加载器其它很简单。只要实现ClassLoader的findClass()方法就行了。
大概如下:
findClass(String name){
byte[] buffer=//读取文件的字节数组
return defineClass(buffer,0,buffer.length);
}
当自定义类加载器加载的类有继承相应的类或实现相应接口的话,必须把相应的父类或接口拷贝到同一路径。因为类加载器在加载子类时,会同时加载父类。
关于类的转型问题:
由于类加载器是相互隔离的,当classLoaderA加载了A类,classLoaderB也加载了A类。这个类对象是不能互相转型的。会报ClassCastException异常。
假如自定义类加载器加载A类时,而A类又实现了接口B时,我们是可以将A类的实例转成B接口的。原因是类加载器在加载A类时,会同时加载A类的所有父类(包括接口).
JAVA类加载器采用了委托模式。当一个类对象己经被加载了,就不会在去加载该类。还是直接返回。那么如何重新加载这个类呢?
实现自定义的类加载器,当类加载完成后。调用相应方法,然后在去掉相应类加载器的引用。这样类不会在存在类加载器中了。
比如:classLoaderA=null(去掉A加载器的引用)