虚拟机类加载机制--类加载器
类与类加载器
对于任意一个类,都需要由加载这个类的类加载器和这个类本身才确定这个类在jvm中的唯一性,每一个类加载器都有独立的类名称空间。比较两个类是否相等,在同一个类加载器的前提下才有意义,否则即使同一class在同一虚拟机内被加载,只要加载它们的类加载器不同,那么这两个类就不相等
package com.wkzhao;
import java.io.IOException;
import java.io.InputStream;
/**
* 输出结果:class com.wkzhao.ClassLoaderTest false
*/
public class ClassLoaderTest {
public static void main(String[] args) throws ClassNotFoundException
, IllegalAccessException, InstantiationException {
ClassLoader myLoader = new ClassLoader() {
@Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
String filename = name.substring(name.lastIndexOf(".") + 1) + ".class";
InputStream is = getClass().getResourceAsStream(filename);
if (is == null) {
return super.loadClass(name);
}
try {
byte[] bytes = new byte[is.available()];
is.read(bytes);
return defineClass(name, bytes, 0, bytes.length);
} catch (IOException e) {
e.printStackTrace();
}
return super.loadClass(name);
}
};
Object obj = myLoader.loadClass("com.wkzhao.ClassLoaderTest").newInstance();
System.out.println(obj.getClass());
System.out.println(obj instanceof ClassLoaderTest);
}
}
双亲委派机制
从java开发人员角度看,类加载器可分为以下三种:
启动类加载器(BootStrap ClassLoader):这个类加载器负责加载JAVA_HOME/lib下的或者被-Xbootclasspath指定路径下的且被虚拟机识别(仅通过名称识别)的类加载到虚拟机内存中。此加载器无法被java程序直接引用。
扩展类加载器(Extension ClassLoader):这个类加载器负责加载JAVA_HOME\lib\ext或者被java.ext.dirs系统变量所指定的路径中所有类库,开发者可以直接使用扩展类加载器。
应用类加载器(Application ClassLoader):这个类加载器是classLoader中的getSystemClassLoader()方法的返回值,一般称为系统类加载器。他负责加载classpath所指定的类库,开发者可以直接使用这个类加载器。一般情况下这个是程序中默认的类加载器。
类加载器之间的层次关系如下图:
870109-20160503202555529-776544675.png
类加载器之间的这种层次关系,称为类加载器的双亲委派模型。双亲委派模型要求除了顶层的启动类加载器外,其余的类加载器都应当有自己的父类加载器。这里类加载的父子关系一般不会以继承来实现,而都是使用组合来服用父加载器的代码。
双亲委派模型是一种组织类加载器之间关系的一种规范,他的工作原理是:如果一个类加载器收到了类加载的请求,它不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成,这样层层递进,最终所有的加载请求都被传到最顶层的启动类加载器中,只有当父类加载器无法完成这个加载请求(它的搜索范围内没有找到所需的类)时,才会交给子类加载器去尝试加载。
这样的好处是:java类随着它的类加载器一起具备了带有优先级的层次关系.这是十分必要的,比如java.langObject,它存放在\jre\lib\rt.jar中,它是所有java类的父类,因此无论哪个类加载都要加载这个类,最终所有的加载请求都汇总到顶层的启动类加载器中,因此Object类会由启动类加载器来加载,所以加载的都是同一个类,如果不使用双亲委派模型,由各个类加载器自行去加载的话,系统中就会出现不止一个Object类,应用程序就会全乱了。