JAVA虚拟机之ClassLoader

问题

今天遇到一个问题,使用YAML解析yaml文件的时候,报pojo类找不到。这种问题一般来说,都是ClassLoader找不到。

在调试态,发现SnakeYaml是用ExtClassLoader,而Pojo类是AppClassLoader。两个类在不同的classloader中,显然找不到,原因是调试的时候误将Yaml的包配置了-Djava.ext.dir参数。

虚拟机的理解

遇到这个问题主要原因要归于java是一门虚拟机语言,在虚拟机加载的机制下,会出现这个问题。

虚拟机语言可以根据虚拟机列举一下,例如Java虚拟机下有Java、Sacla、groovy等,erlang虚拟机下有erlang、xlieri等。对于虚拟机语言,要想掌握好,就必须了解底层的虚拟机机制,就如C语言必须了解c86架构一样。

而Java虚拟机在《深入Java虚拟机》一书中有详细介绍,内存回收机制、类加载机制、代码解析二级制码和加载。对于应用者,掌握前两者就够了,后者是Java虚拟机商新语言开发者才要掌握的层次。

ClassLoader

对于ClassLoader,有很多细节,这里只关注对这个问题有用的部分。

一个Java虚拟机,对于程序员有用的是

  • Bootstrap ClassLoader:负责加载\lib目录中的类库,无法被Java程序直接引用;
  • Extension ClassLoader:负责加载\lib\ext,开发者可以直接使用;
  • Application ClassLoader:加载ClassPath上所指定的类库,如果没有自己定义过自己的类加载器则会使用它;

关系如下:


JAVA虚拟机之ClassLoader_第1张图片

先了解一个概念,父委托机制
在父委托机制中,除了Java虚拟机自带的根类加载器以外,其余的类加载器都有且只有一个父加载器,各个加载器按照父子关系形成了树形结构。

当Java程序请求加载器loader1加载Sample类时,loader1首先委托自己的父加载器去加载Sample类,若父加载器能加载,则由父加载器完成加载任务,否则才由loader1本身加载Sample类。

了解了上述知识,回头再看看我们的问题:
ExtClassLoader加载了Yaml,AppClassLoader加载了Pojo类,当Yaml调动loadAs(file, Pojo.class)方法时,会用ExtClassLoader去加载Pojo类,这时就会找不到Pojo类,导致异常。

结论

对于知识要知纵横,但不要像在学校学习一样学习所有细节,要着重再对自己有用的部分。

你可能感兴趣的:(JAVA虚拟机之ClassLoader)