JAVA中如何将一个类加载多次_Java的类加载机制(ClassLoader)

论坛 期权论坛     
选择匿名的用户   2021-5-26 13:47   0   0
<div style="font-size:16px;">
<p>一、什么是ClassLoader?</p>
<p>大家都知道,当我们写好一个Java程序之后,不是管是CS还是BS应用,都是由若干个.class文件组织而成的一个完整的Java应用程序,当程序在运行时,即会调用该程序的一个入口函数来调用系统的相关功能,而这些功能都被封装在不同的class文件当中,所以经常要从这个class文件中要调用另外一个class文件中的方法,如果另外一个文件不存在的,则会引发系统异常。而程序在启动的时候,并不会一次性加载程序所要用的所有class文件,而是根据程序的需要,通过Java的类加载机制(ClassLoader)来动态加载某个class文件到内存当中的,从而只有class文件被载入到了内存之后,才能被其它class所引用。所以ClassLoader就是用来动态加载class文件到内存当中用的。</p>
<p>二、Java默认提供的三个ClassLoader</p>
<p>BootStrap ClassLoader:称为启动类加载器,是Java类加载层次中最顶层的类加载器,负责加载JDK中的核心类库,如:rt.jar、resources.jar、charsets.jar等,可通过如下程序获得该类加载器从哪些地方加载了相关的jar或class文件:</p>
<p>URL[] urls &#61; sun.misc.Launcher.getBootstrapClassPath().getURLs();</p>
<p>for (int i &#61; 0; i &lt; urls.length; i&#43;&#43;) {<!-- --></p>
<p>System.out.println(urls[i].toExternalForm());</p>
<p>}</p>
<p>以下内容是上述程序从本机JDK环境所获得的结果:</p>
<p>file:/C:/Program%20Files/Java/jdk1.6.0_22/jre/lib/resources.jar</p>
<p>file:/C:/Program%20Files/Java/jdk1.6.0_22/jre/lib/rt.jar</p>
<p>file:/C:/Program%20Files/Java/jdk1.6.0_22/jre/lib/sunrsasign.jar</p>
<p>file:/C:/Program%20Files/Java/jdk1.6.0_22/jre/lib/jsse.jar</p>
<p>file:/C:/Program%20Files/Java/jdk1.6.0_22/jre/lib/jce.jar</p>
<p>file:/C:/Program%20Files/Java/jdk1.6.0_22/jre/lib/charsets.jar</p>
<p>file:/C:/Program%20Files/Java/jdk1.6.0_22/jre/classes/</p>
<p>其实上述结果也是通过查找sun.boot.class.path这个系统属性所得知的。</p>
<p>System.out.println(System.getProperty(&#34;sun.boot.class.path&#34;));</p>
<p>打印结果:C:\Program Files\Java\jdk1.6.0_22\jre\lib\resources.jar;C:\Program Files\Java\jdk1.6.0_22\jre\lib\rt.jar;C:\Program Files\Java\jdk1.6.0_22\jre\lib\sunrsasign.jar;C:\Program Files\Java\jdk1.6.0_22\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.6.0_22\jre\lib\jce.jar;C:\Program Files\Java\jdk1.6.0_22\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.6.0_22\jre\classes</p>
<p>Extension ClassLoader:称为扩展类加载器,负责加载Java的扩展类库,默认加载JAVA_HOME/jre/lib/ext/目下的所有jar。</p>
<p>App ClassLoader:称为系统类加载器,负责加载应用程序classpath目录下的所有jar和class文件。</p>
<p>注意: 除了Java默认提供的三个ClassLoader之外,用户还可以根据需要定义自已的ClassLoader,而这些自定义的ClassLoader都必须继承自java.lang.ClassLoader类,也包括Java提供的另外二个ClassLoader(Extension ClassLoader和App ClassLoader)在内,但是Bootstrap ClassLoader不继承自ClassLoader,因为它不是一个普通的Java类,底层由C&#43;&#43;编写,已嵌入到了JVM内核当中,当JVM启动后,Bootstrap ClassLoader也随着启动,负责加载完核心类库后,并构造Extension ClassLoader和App ClassLoader类加载器。</p>
<p>三、ClassLoader加载类的原理</p>
<p>1、原理介绍</p>
<p>双亲委派模型工作过程是:如果一个类加载器收到类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器完成。每个类加载器都是如此,只有当父加载器在自己的搜索范围内找不到指定的类时(即ClassNotFoundException),子加载器才会尝试自己去加载。</p>
<p>ClassLoader使用的是双亲委托模型来搜索类的,每个ClassLoader实例都有一个父类加载器的引用(不是继承的关系,是一个包含的关系),虚拟机内置的类加载器(Bootstrap ClassLoader)本身没有父类加载器,但可以用作其它ClassLoader实例的的父类加载器。当一个ClassLoader实例需要加载某个类时,它会试图亲自搜索某个类之前,先把这个任务委托给它的父类加载器,这个过程是由上至下依次检查的,首先由最顶层的类加载器Bootstrap ClassLoader试图加载,如果没加载到,则把任务转交给Extension ClassLoader试图加载,如果也没加载到,则转交给App ClassLoader 进行加载,如果它也没有加载得到的话,则返回给委托的发起者,由它到指定的文件系统或网络等URL中加载该类。如果它们都没有加载到这个类时,则抛出ClassNotFoundException异常。否则将这个找到的类生成一个类的定义,并将它加载到内存当中,最后返回这个类在内存中的Class实例对象。</p>
分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:3875789
帖子:775174
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP