【转】 java ClassLoader笔记(一)
2012-06-01 13:16
197 查看
一、Sun JDK Classloader体系
1.层次关系
Bootstrap: 加载rt.jar
<-Extension:加载 jre/ext/*.jar
<-System:加载CLASSPATH中的jar
<-UserDefined加载用户自定义包类
2.特殊点
Bootstrap ClassLoader为C++所写,Extension ClassLoader的parent为null,其中,getParent返回实例化本ClassLoader的ClassLoader,并不是superClass。
3.上级委托
很反感“双亲委托”这个翻译。给人第一印象要两个类去委托,而且,很容易感觉是继承关系。上级委托多好,立马减轻了理解难度。
上级委托的优点:
a.避免父子重复加载
b.避免jdk核心类被替代。比如String.class,在rt.jar包中。如果用户自己写了一个恶意代码,
由此想象一下我们经常遇到的,不同版本的jar包,出现冲突的原因(未经测试):
testv1.jar
testv2.jar
a.如果两个包是独立的,不被其他包中的class引用:
如果两个包中的文件个数和名称完全一致,不会有冲突。因为同样的版本只加载一次。
如果v2中有新的类,而加载的是testv1.jar,v2的新类就可能使用到v1的其他旧类,导致方法找不到或者逻辑错乱。
如果加载的是testv2.jar,而v2是向下兼容,只增加类和方法,没有冲突。因为v1的类都不加载
如果加载的是testv2.jar,只是删除了旧版本一些相对独立的类,这样旧版本中的这些类会被加载,并可以正常使用。
b.如果test包还有其他类引用,那就不好说了。类似上述情况,可能会出现冲突。
二、源码理解
[java] view
plaincopy
protected synchronized Class loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
// 首先检查该name指定的class是否有被加载
Class c = findLoadedClass(name);
if (c == null) {
try {
if (parent != null) {
//如果parent不为null,则调用parent的loadClass进行加载
= parent.loadClass(name, false);
} else {
//parent为null,则调用BootstrapClassLoader进行加载
c = findBootstrapClass0(name);
}
} catch (ClassNotFoundException e) {
//如果仍然无法加载成功,则调用自身的findClass进行加载
c = findClass(name);
}
}
if (resolve) {
resolveClass(c);
}
return c;
}
从这里也可以了解,ClassNotFoundException是因为什么情况产生了。就是当前类的类加载器没有找到对应jar或class文件。
Class.forname(String clazzName)实际上是使用了一个默认的类加载器,
[java] view
plaincopy
public static Class<?> forName(String className)
throws ClassNotFoundException {
return forName0(className, true, ClassLoader.getCallerClassLoader());
}
从这里可以看出,使用的是调用Class.forname这个类所被加载的类加载器,对于一般的应用,就是SystemClassLoader,sun.misc.Launcher$AppClassLoader是一个实现
工具代码:用于查看Extension ClassLoader所加载的包
[java] view
plaincopy
try {
URL[] extURLs = ((URLClassLoader) ClassLoader
.getSystemClassLoader().getParent()).getURLs();
for (int i = 0; i < extURLs.length; i++) {
System.out.println(extURLs[i]);
}
} catch (Exception e) {
}
其他:
JVM中,一个类是否装载,由其fully qualified class name,也就是加包名的完整类名如com.sss.test.Test,及其装载器唯一决定。
也就是说,即使是同一个类,如果装载器不同,就可能被装载多次。
1.层次关系
Bootstrap: 加载rt.jar
<-Extension:加载 jre/ext/*.jar
<-System:加载CLASSPATH中的jar
<-UserDefined加载用户自定义包类
2.特殊点
Bootstrap ClassLoader为C++所写,Extension ClassLoader的parent为null,其中,getParent返回实例化本ClassLoader的ClassLoader,并不是superClass。
3.上级委托
很反感“双亲委托”这个翻译。给人第一印象要两个类去委托,而且,很容易感觉是继承关系。上级委托多好,立马减轻了理解难度。
上级委托的优点:
a.避免父子重复加载
b.避免jdk核心类被替代。比如String.class,在rt.jar包中。如果用户自己写了一个恶意代码,
由此想象一下我们经常遇到的,不同版本的jar包,出现冲突的原因(未经测试):
testv1.jar
testv2.jar
a.如果两个包是独立的,不被其他包中的class引用:
如果两个包中的文件个数和名称完全一致,不会有冲突。因为同样的版本只加载一次。
如果v2中有新的类,而加载的是testv1.jar,v2的新类就可能使用到v1的其他旧类,导致方法找不到或者逻辑错乱。
如果加载的是testv2.jar,而v2是向下兼容,只增加类和方法,没有冲突。因为v1的类都不加载
如果加载的是testv2.jar,只是删除了旧版本一些相对独立的类,这样旧版本中的这些类会被加载,并可以正常使用。
b.如果test包还有其他类引用,那就不好说了。类似上述情况,可能会出现冲突。
二、源码理解
[java] view
plaincopy
protected synchronized Class loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
// 首先检查该name指定的class是否有被加载
Class c = findLoadedClass(name);
if (c == null) {
try {
if (parent != null) {
//如果parent不为null,则调用parent的loadClass进行加载
= parent.loadClass(name, false);
} else {
//parent为null,则调用BootstrapClassLoader进行加载
c = findBootstrapClass0(name);
}
} catch (ClassNotFoundException e) {
//如果仍然无法加载成功,则调用自身的findClass进行加载
c = findClass(name);
}
}
if (resolve) {
resolveClass(c);
}
return c;
}
从这里也可以了解,ClassNotFoundException是因为什么情况产生了。就是当前类的类加载器没有找到对应jar或class文件。
Class.forname(String clazzName)实际上是使用了一个默认的类加载器,
[java] view
plaincopy
public static Class<?> forName(String className)
throws ClassNotFoundException {
return forName0(className, true, ClassLoader.getCallerClassLoader());
}
从这里可以看出,使用的是调用Class.forname这个类所被加载的类加载器,对于一般的应用,就是SystemClassLoader,sun.misc.Launcher$AppClassLoader是一个实现
工具代码:用于查看Extension ClassLoader所加载的包
[java] view
plaincopy
try {
URL[] extURLs = ((URLClassLoader) ClassLoader
.getSystemClassLoader().getParent()).getURLs();
for (int i = 0; i < extURLs.length; i++) {
System.out.println(extURLs[i]);
}
} catch (Exception e) {
}
其他:
JVM中,一个类是否装载,由其fully qualified class name,也就是加包名的完整类名如com.sss.test.Test,及其装载器唯一决定。
也就是说,即使是同一个类,如果装载器不同,就可能被装载多次。
相关文章推荐
- java开发笔记——classLoader
- Java中ClassLoader笔记
- JAVA ClassLoader笔记
- 【JAVA IO】_数据操作流笔记
- java对象序列化学习笔记
- Java笔记001_Java里集合分类
- JAVA学习笔记(三)
- java 多线程笔记
- Java 学习笔记10:获取POST数据以及简单模板输出
- 孙鑫-JAVA学习笔记(1-3)
- JAVA的面向对象编程高手笔记
- Java自学笔记(第六天)-static-类变量-对象变量-javadoc文档-static代码块-单例设计模式
- Java学习笔记(4):2.数组
- java自学笔记6:UML简介+阶段练习
- Java学习笔记之 File构造方法
- [Java视频笔记]day14
- (46)Java学习笔记——多线程 / 线程的生命周期
- 深入理解Java ClassLoader原理
- JAVA学习笔记——集合Collection
- 黑马程序员_JAVA 学习笔记20 WEB篇7