jvm的类的加载一般有如下过程:
- 装载
- 链接(验证,准备,解析(可选择))
- 卸载
关系如图:
加载器也是个类,分为三类加载器:
- 引导加载器(用C++编写,属于JVM一部分)
- 扩展加载器
- 应用加载器
用户还可以自己定义加载器,运行一个程序系统默认的采用应用加载器,扩展加载器继承了引导加载器,应用加载器继承了扩展加载器。引导加载器会加载classpath指定路径下的jar包,一般为jre的核心jar包。在lib的ext文件夹下为扩展加载器加载的jar包。
加载一个类首先使用找父类加载器是否能加载否则才让自己加载,如果一个类里有引用,这个引用的类就从加载外层类的加载器开始寻找父类加载器。
System.out.println(Test5.class.getClassLoader().getParent());
运行结果:null
因为引导加载器是编写JVM的语言,所以无法打印出来。
System.out.println(Test5.class.getClassLoader().getParent());
运行结果:
sun.misc.Launcher$ExtClassLoader@659e0bfd
为应用加载器的父类为扩展加载器
System.out.println(Test5.class.getClassLoader());
运行结果:
sun.misc.Launcher$AppClassLoader@c387f44
打印出该类的加载器为应用加载器
- 定义两个类:
/**
* @author micro_hz
*
*/
//分别打印出两个类的加载器
public class Test1 {
public static void main(String args[])
{
System.out.println(Test5.class.getClassLoader());
Test2 t = new Test2();
t.printClassLoader();
}
}
/**
@author:micro_hz
2015年8月8日
*/
public class Test2 {
public void printClassLoader()
{
System.out.println(this.getClass().getClassLoader());
}
}
运行结果:
sun.misc.Launcher$AppClassLoader@c387f44
sun.misc.Launcher$AppClassLoader@c387f44
果然都是采用应用加载器加载的。
将Test2jar包放在扩展ext文件夹下,Test1不放。运行结果:
sun.misc.Launcher$AppClassLoader@73d16e93
sun.misc.Launcher$ExtClassLoader@33909752
Test1从应用加载器从扩展加载器没找到,则直接从应用加载器加载, 引用的Test2也从应用加载器开始请求扩展加载器找到了加载类,因此运行为此结果。
然后我们将Test1打为jar包放在jre\lib\ext 目录下,将Test2jar不放在ext和classes包里。
运行结果为:
sun.misc.Launcher$ExtClassLoader@7852e922
Exception in thread "main" java.lang.NoClassDefFoundError: Test2
at dataStrutcure.Test1.main(Test1.java:13)
Caused by: java.lang.ClassNotFoundException: dataStrutcure.Test2
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
... 1 more
因为Test1加载的时候首先从应用加载器找到父类加载器扩展加载器,发现在扩展器可以加载,然后再请求引导加载器,发现不能加载,所以最后由扩展加载器加载。在Test1中应用了Test2,由于Test1是由扩展加载器加载的,因此Test2直接从扩展加载开始请求引导加载器发现不能加载,因此尝试从扩展加载器加载,发现不能加载因此抛出ClassNotFound异常。
如果我们把Test2也jar包放在ext就会都从扩展加载器加载了:
sun.misc.Launcher$ExtClassLoader@7852e922
sun.misc.Launcher$ExtClassLoader@7852e922
关于类加载的路径请点击这里
相关引用这里写链接内容