首页 > 代码库 > 关于类加载器那点破事儿

关于类加载器那点破事儿

Java的类加载器就是负责把.class文件加载到内存中的工具。据说,只有.class被加载如内存后才能被称为字节码。

Java的类加载器呈父子级联关系:

BootStrap --> ExtClassLoader --> AppClassLoader -- > 自定义类加载器

-- BootStrap 跟加载器,负责加载rt.jar这类的由Java自身提供的类,他是由C++编写的,所以当我们在程序里想要get他时,返回的是null

-- ExtClassLoader 扩展类加载器,负责加载jre/lib/ext 目录下的类

-- AppClassLoader 应用类加载器,负责加载classpath下的类

-- 自定义类加载器 继承自ClassLoader,可以实现自定义的类加载方式

 

Java的类加载使用所谓的“全盘委托”机制:

-- 当要加载一个类时,从负责加载这个类的类加载器开始,往上回朔所有父类加载器,如果被回朔过程中的某一个类加载器成功加载,则加载完成,如果回溯中所有父类加载器都无法加载(PS:这里说的无法加载是指当前这个类加载器负责的加载范围内找不到与这个要加载类的名字相同的类),则返还给负责加载这种类的类加载器进行加载,如果依旧无法加载,则会抛出ClassNotFoundException。也就是说,如果爸爸爷爷能加载这个类,就进行加载,如果不能加载,则还给儿子/孙子自己去加载。这个和实例化类比较类似,我们在实例化一个类时,JVM也是去实例化这个类的所有直接、间接父类。

-- 全盘委托机制的好处:保证了类加载的安全。比如我们自己写一个String类,当类开始加载时,会往上回朔,到了BootStrap根加载器,跟加载器发现他可以加载String类,但是他不会加载我们写的这个String类,而是去加载他本身负责范围内的String类,这样就保证了String类的正确加载,而不是让我们自定义的String类去覆盖了原有的String类。

 

自定义类加载器在很多地方都有出现,比如Tomcat里面就有很多自定义类加载器。实现一个自定义类加载器只需要继承ClassLoader,再重写findClass方法即可:

1 public class MyClassLoader extends ClassLoader {2 3     @Override4     protected Class<?> findClass(String name) throws ClassNotFoundException {5         return super.findClass(name);6     }7 8 }