类加载器的加载机制

加载阶段中的“通过一个类的全限定名来获取此类的二进制字节流”这个动作放到jvm外部去实现,以便让应用程序自己决定如何去获取所需要的类。实现这个动作的代码模版被称为“类加载器”。
双亲委派模型
站在jvm角度讲,只有两种类加载器:一种是启动类加载器(Bootstrap ClassLoader),这个类加载器是由C++实现的,是jvm的一部分。另一种就是其他所有的类加载器,这些由java语言实现,独立于jvm,并且全部继承自抽象类java.lang.ClassLoader。
划分的更细致些:
1、启动类加载器bootstrap classloader
负责将存放在JAVA_HOME/lib下的类库加载到虚拟机内存中,该类加载器无法被java程序直接引用。
2、拓展类加载器
3、应用程序类加载器:这个是由classloader中的getSystemClassLoader()方法的返回值,所以一般称为系统类加载器。如果系统内部没有自定义的加载器,则系统类加载器就是默认的类加载器
类加载器的加载机制
如果一个类加载器收到了类的加载请求,它首先不会自己去尝试加载这个类,而是把请求委派给父类加载器去完成,每一层的类加载器都是如此,因此所有的 加载请求最终都应该传送到顶层的启动类加载器中,只有当父加载器反馈自己无法完成加载请求时,子加载器才会尝试自己去加载。
//下面是一个简单的自定义classloader的实现,并且与默认加载器比较加载结果
packageclassloadertest;
importjava.io.InputStream;
publicclassClassLoaderTest{
publicstaticvoidmain(String[]args)throwsException{
ClassLoadermyLoader=newClassLoader(){
publicClass<?>loadClass(Stringname){
byte[]b=null;
try{
StringfileName=name.substring(name.lastIndexOf(".")+1)
+".class";
System.out.println(fileName);
InputStreamis=getClass().getResourceAsStream(fileName);
if(is==null){
returnsuper.loadClass(name);
}
b=newbyte[is.available()];
is.read(b);
}catch(Exceptione){
}
returndefineClass(name,b,0,b.length);
}
};
Objectobj=myLoader.loadClass("classloadertest.A").newInstance();
System.out.println(obj.getClass());
System.out.println(objinstanceofclassloadertest.A);
}
}
结果如下
A.class
Object.class
classclassloadertest.A
false