Jvm加载器加载顺序

来源:互联网 发布:汇编 数组 nasm 编辑:程序博客网 时间:2024/04/29 08:10

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_hz2015年8月8日 */public class Test2 {    public void printClassLoader()    {    System.out.println(this.getClass().getClassLoader());    }}

运行结果:

sun.misc.Launcher$AppClassLoader@c387f44sun.misc.Launcher$AppClassLoader@c387f44

果然都是采用应用加载器加载的。
将Test2jar包放在扩展ext文件夹下,Test1不放。运行结果:

sun.misc.Launcher$AppClassLoader@73d16e93sun.misc.Launcher$ExtClassLoader@33909752

Test1从应用加载器从扩展加载器没找到,则直接从应用加载器加载, 引用的Test2也从应用加载器开始请求扩展加载器找到了加载类,因此运行为此结果。
然后我们将Test1打为jar包放在jre\lib\ext 目录下,将Test2jar不放在ext和classes包里。
运行结果为:

sun.misc.Launcher$ExtClassLoader@7852e922Exception 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@7852e922sun.misc.Launcher$ExtClassLoader@7852e922

关于类加载的路径请点击这里
相关引用这里写链接内容

0 0
原创粉丝点击