深入探讨Java类加载器

 

  本篇文章主要是详细写一下个人对Java ClassLoader的理解。

    首先回顾一下,Java虚拟机载入java类的步骤:java文件经过编译器编译后变成字节码文件(.class文件),类加载器(ClassLoader)读取.class文件,并且转换成java.lang.Class的一个实例,最后通过newInstance方法创建该类的一个对象。ClassLoader的作用就是根据一个类名,找到对应的字节码,根据这些字节码定义出对应的类,该类就是java.lang.Class的一个实例。


类加载器的组织结构

    java有三个初始类加载器,当java虚拟机启动时,它们会按照以下顺序启动:bootstrap classloader -> extension classloader -> system classloader。三者的关系:bootstrap classloader是extension classloader的parent,extension classloader是system classloader的parent。

bootstrap classloader

    它是最原始的类加载器,并不是由java代码写的,是由原生代码编写的。Java有一次编译、所有平台运行的效果,就是因为它写了一份功能相同,但针对不同平台不同语言实现的底层代码。它负责加载java核心库,大家可运行以下代码,看看自己本地的java核心库在哪里:

  1. <code class="hljs go">URL[] urls=sun.misc.Launcher.getBootstrapClassPath().getURLs();  

  2. <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i < urls.length; i++) {  

  3.     System.out.<span class="hljs-built_in">println</span>(urls[i].toExternalForm());  

  4. }</code>  

本人的运行结果:

  1. <code class="hljs groovy"><span class="hljs-string">file:</span><span class="hljs-regexp">/home/</span>eric<span class="hljs-regexp">/jdk1.6.0_35/</span>jre<span class="hljs-regexp">/lib/</span>resources.jar  

  2. <span class="hljs-string">file:</span><span class="hljs-regexp">/home/</span>eric<span class="hljs-regexp">/jdk1.6.0_35/</span>jre<span class="hljs-regexp">/lib/</span>rt.jar  

  3. <span class="hljs-string">file:</span><span class="hljs-regexp">/home/</span>eric<span class="hljs-regexp">/jdk1.6.0_35/</span>jre<span class="hljs-regexp">/lib/</span>sunrsasign.jar  

  4. <span class="hljs-string">file:</span><span class="hljs-regexp">/home/</span>eric<span class="hljs-regexp">/jdk1.6.0_35/</span>jre<span class="hljs-regexp">/lib/</span>jsse.jar  

  5. <span class="hljs-string">file:</span><span class="hljs-regexp">/home/</span>eric<span class="hljs-regexp">/jdk1.6.0_35/</span>jre<span class="hljs-regexp">/lib/</span>jce.jar  

  6. <span class="hljs-string">file:</span><span class="hljs-regexp">/home/</span>eric<span class="hljs-regexp">/jdk1.6.0_35/</span>jre<span class="hljs-regexp">/lib/</span>charsets.jar  

  7. <span class="hljs-string">file:</span><span class="hljs-regexp">/home/</span>eric<span class="hljs-regexp">/jdk1.6.0_35/</span>jre<span class="hljs-regexp">/lib/</span>modules/jdk.boot.jar  

  8. <span class="hljs-string">file:</span><span class="hljs-regexp">/home/</span>eric<span class="hljs-regexp">/jdk1.6.0_35/</span>jre/classes</code>  

extension classloader

    它用来加载JRE的扩展目录(JAVA_HOME/jre/lib/ext或java.ext.dirs系统属性指定的)JAR的类包。注意,因为它是bootstrap classloader加载的,所以当你运行:

  1. <code class="hljs kotlin">ClassLoader extensionClassloader=ClassLoader.getSystemClassLoader().getParent();  

  2. System.<span class="hljs-keyword">out</span>.println(<span class="hljs-string">"the parent of extension classloader : "</span>+extensionClassloader.getParent());</code>  

输出的是:the parent of extension classloader : null

system classloader

它用于加载classpath目录下的jar包,我们写的java类,一般都是由它加载,除非你自己制定个人的类加载器。


全盘负责委托机制

classloader加载类时,使用全盘负责委托机制,可以分开两部分理解:全盘负责,委托。

全盘负责机制:若类A调用了类B,则类B和类B所引入的所有jar包,都由类A的类加载器统一加载。

委托机制:类加载器在加载类A时,会优先让父加载器加载,当父加载器加载不到,再找父父加载器,一直找到bootstrap  classloader都找不到,才自己去相关的路径去寻找加载。以下是ClassLoader的源码:

50000+
5万行代码练就真实本领
17年
创办于2008年老牌培训机构
1000+
合作企业
98%
就业率

联系我们

电话咨询

0532-85025005

扫码添加微信