A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 刘宣超 中级黑马   /  2014-9-13 22:41  /  1370 人查看  /  2 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

类加载器就是记载类的一个工具。

我们在java程序中用到一个类,首先java 虚拟机会把这个类的字节码从硬盘加载到内存里面来,在对它进行一些处理,处理完之后就是字节码。通常这个字节码会放在硬盘指定的目录下。

jvm里面有多个类加载器。系统默认有三个类加载器。每个加载器都负责加载特定位置的类。每个加载器都有自己加载的区域,他们分别是 BootStrap、extClassLoader、AppClassLoader。

类加载器他也是一个类,他也需要被加载,那么他是被谁加载的呢?

在java虚拟机内核中有一个和虚拟机并存的一个类加载器BootStrap,他不是java中的一个类,当java虚拟机启动时他就跟着启动了,他是用C++语言写的一段二进制代码。 所以他不需要加载器。

在Class类中有这样一个方法。getClassLoader()他是获取加载本类的类加载器返回一个ClassLoader 类。

ClassLoaderTest{
public static void main(String[] args){
// 获取ClassLoaderTest类的字节码,然后获取加载他的那个类加载器,
//通过获取类加载器的字节码,然后获取类加载器的名字。
syso:ClassLoaderTest.class.getClassLoader().getClass().getName();

//打印的类加载器是AppClassLoader也就是说这个类是由AppClassLoader加载的。

syso:System.class.getClassLoader().getClass().getName();

//打印结果为null因为,加载这个类的类加载器不是Java类而是之前说过的那个嵌套在java  //虚拟机中的一个类加载器,所以获得不了他的字节码和他的名字。

}
}

java虚拟机中给我们提供了三个类加载器他们是由子父关系组成的。

下面的一段代码把他们的关系给打印出来了
//获取他的类加载器
ClassLoader loader = ClassLoaderTest.class.getClassLoader();
//循环只要不是BootStrap就一直循环
while(loader !=null){
//打印当前类加载器的名字
syso:loader.getClass().getName();

//把当前类加载器改为他的爸爸。
loader = loader.getParent();

}
//完了最后打印最大的类加载器;
syso: loader;

以上打印结果是: AppClassLoader

     ExtClassLoader

     null;

这个体系就出来了。我们 可以很形象的吧AppClassLoader比喻成 孙子,ExtClassLoader比喻成爸爸,null比喻成爷爷。

AppClassLoader:加载的是我们写的ClassPath路径下指定的所有jar包 或目录

ExtClassLoader: 加载的是JDK里面jre\ext文件里面的jar里面的类。

null : 加载的是jre\lib里面的rt.jar包里面的类里面都是系统类。

如果在在多个目录下都有这个class 文件java虚拟机会使用哪个类加载器去加载呢?

这就涉及到了委托机制。

首先用当前线程的类加载器去加载线程中的第一个类。
在Thread中有这样一个方法可以指定类加载器setContextClassLoader(ClassLoader c1)
一旦指定 了该线程运行到A类就用这个加类载器去加载如果A类引用了B类,java虚拟机会用加载A类 的类加载器去加载B类。

还可以调用ClassLoader.loaderClass()方法来指定类加载器,去加载类;
每个类加载器加载类的时候先不加载会先委托给上级,然后上级有会委托给上级。最后也就是”爷爷“他上 面没人了,所以他就加载了,如果找不到文件,不会报异常,他会给自己的下一级,知道给了发起者为止。
如果发起者还是没有找到Class文件或者jar包的话那么就直接报异常了。
这时发起者才加载类,也就是说每个类加载器都会先让BootSraat加载,指定的类加载器是最后才加载类 的。

2 个回复

倒序浏览
今天看完高新技术在回来品味下,先谢过。
回复 使用道具 举报
谢谢分享
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马