`
collegeyuan
  • 浏览: 30957 次
  • 性别: Icon_minigender_2
  • 来自: 上海
文章分类
社区版块
存档分类
最新评论

ClassLoader加载的双亲委托模式

 
阅读更多

要深入了解ClassLoader,首先就要知道ClassLoader是用来干什么的,顾名思义,它就是用来加载Class文件到JVM,以供程序使用 的。我们知道,java程序可以动态加载类定义,而这个动态加载的机制就是通过ClassLoader来实现的,所以可想而知ClassLoader的重 要性如何。

看到这里,可能有的朋友会想到一个问题,那就是既然ClassLoader是用来加载类到JVM中的,那么ClassLoader又是如何被加载呢?难道它不是java的类?

没有错,在这里确实有一个ClassLoader不是用java语言所编写的,而是JVM实现的一部分,这个ClassLoader就是 bootstrap classloader(启动类加载器),这个ClassLoader在JVM运行的时候加载java核心的API以满足java程序最基本的需求,其中 就包括用户定义的ClassLoader,这里所谓的用户定义是指通过java程序实现的ClassLoader,一个是ExtClassLoader, 这个ClassLoader是用来加载java的扩展API的,也就是/lib/ext中的类,一个是AppClassLoader,这个 ClassLoader是用来加载用户机器上CLASSPATH设置目录中的Class的,通常在没有指定ClassLoader的情况下,程序员自定义 的类就由该ClassLoader进行加载。

当运行一个程序的时候,JVM启动,运行bootstrap classloader,该ClassLoader加载java核心API(ExtClassLoader和AppClassLoader也在此时被加 载),然后调用ExtClassLoader加载扩展API,最后AppClassLoader加载CLASSPATH目录下定义的Class,这就是一 个程序最基本的加载流程。

上面大概讲解了一下ClassLoader的作用以及一个最基本的加载流程,接下来将讲解一下ClassLoader加载的方式,这里就不得不讲一下ClassLoader在这里使用了双亲委托模式进行类加载。

每一个自定义ClassLoader都必须继承ClassLoader这个抽象类,而每个ClassLoader都会有一个parent ClassLoader,我们可以看一下ClassLoader这个抽象类中有一个getParent()方法,这个方法用来返回当前 ClassLoader的parent,注意,这个parent不是指的被继承的类,而是在实例化该ClassLoader时指定的一个 ClassLoader,如果这个parent为null,那么就默认该ClassLoader的parent是bootstrap classloader,这个parent有什么用呢?

我们可以考虑这样一种情况,假设我们自定义了一个ClientDefClassLoader,我们使用这个自定义的ClassLoader加载 java.lang.String,那么这里String是否会被这个ClassLoader加载呢?事实上java.lang.String这个类并不 是被这个ClientDefClassLoader加载,而是由bootstrap classloader进行加载,为什么会这样?实际上这就是双亲委托模式的原因,因为在任何一个自定义ClassLoader加载一个类之前,它都会先 委托它的父亲ClassLoader进行加载,只有当父亲ClassLoader无法加载成功后,才会由自己加载,在上面这个例子里,因为 java.lang.String是属于java核心API的一个类,所以当使用ClientDefClassLoader加载它的时候,该 ClassLoader会先委托它的父亲ClassLoader进行加载,上面讲过,当ClassLoader的parent为null 时,ClassLoader的parent就是bootstrap classloader,所以在ClassLoader的最顶层就是bootstrap classloader,因此最终委托到bootstrap classloader的时候,bootstrap classloader就会返回String的Class。

我们来看一下ClassLoader中的一段源代码:

 
复制代码
     protected synchronized Class loadClass(String name, boolean resolve) throws ClassNotFoundException{  
         // 首先检查该name指定的class是否有被加载  
         Class c = findLoadedClass(name);  
         if (c == null) {  
             try {  
                 if (parent != null) {  
                     //如果parent不为null,则调用parent的loadClass进行加载  
                     c = parent.loadClass(name, false);  
                 }else{  
                     //parent为null,则调用BootstrapClassLoader进行加载  
                     c = findBootstrapClass0(name);  
                 }  
             }catch(ClassNotFoundException e) {  
                 //如果仍然无法加载成功,则调用自身的findClass进行加载              
                 c = findClass(name);  
             }  
         }  
         if (resolve) {  
             resolveClass(c);  
         }  
         return c;  
    } 
复制代码

 

 



从上面一段代码中,我们可以看出一个类加载的大概过程与之前我所举的例子是一样的,而我们要实现一个自定义类的时候,只需要实现findClass方法即可。

为什么要使用这种双亲委托模式呢?

第一个原因就是因为这样可以避免重复加载,当父亲已经加载了该类的时候,就没有必要子ClassLoader再加载一次。

第二个原因就是考虑到安全因素,我们试想一下,如果不使用这种委托模式,那我们就可以随时使用自定义的String来动态替代java核心api中定义类 型,这样会存在非常大的安全隐患,而双亲委托的方式,就可以避免这种情况,因为String已经在启动时被加载,所以用户自定义类是无法加载一个自定义的 ClassLoader。

上面对ClassLoader的加载机制进行了大概的介绍,接下来不得不在此讲解一下另外一个和ClassLoader相关的类,那就是Class类,每 个被ClassLoader加载的class文件,最终都会以Class类的实例被程序员引用,我们可以把Class类当作是普通类的一个模板,JVM根 据这个模板生成对应的实例,最终被程序员所使用。

我们看到在Class类中有个静态方法forName,这个方法和ClassLoader中的loadClass方法的目的一样,都是用来加载class的,但是两者在作用上却有所区别。

分享到:
评论

相关推荐

    ClassLoader类加载机制和原理详解

    双亲委派模型使得系统类(如java.*开头的类)由Bootstrap ClassLoader加载,而用户自定义类由应用程序类加载器(AppClassLoader)加载。这避免了类的冲突,保持了系统类库的稳定性。但有时我们可能需要打破这种模型...

    使用classloader动态加载Class

    2. **双亲委派模型**:Java的类加载机制遵循双亲委派模型,即当一个类加载器接收到加载类的请求时,它会先委托给父类加载器去加载,只有当父类加载器无法加载时,当前类加载器才会尝试自己加载。这种设计有助于防止...

    ClassLoader

    通过对`ClassLoader`的基本概念、工作原理、双亲委托机制以及不同类型的类加载器的了解,我们可以更好地理解Java类加载的过程及其背后的设计哲学。这对于深入理解Java虚拟机的内部机制以及开发高质量的应用程序都至...

    Java ClassLoader学习总结

    ClassLoader 使用了双亲委托模式进行类加载,每一个自定义的 ClassLoader 都必须继承 ClassLoader 这个抽象类,而每个 ClassLoader 都会有一个 parent ClassLoader。 ClassLoader 的种类有三种:bootstrap ...

    Java ClassLoader定制实例

    接着,Extension ClassLoader加载扩展类库,然后是App ClassLoader加载应用程序的类路径下的类。每个ClassLoader都有其父ClassLoader,它们形成了一个层次结构,子ClassLoader可以委托父ClassLoader去加载类,避免了...

    S18-ClassLoader类加载流程1

    这是一种设计模式,当类加载器接收到加载类的请求时,它首先会将请求委派给其父类加载器处理,只有在父类加载器无法加载时,子类加载器才会尝试加载。这种模型保证了类的唯一性,避免了类的重复加载和冲突。 4. **...

    ClassLoader运行机制 自己写的

    这意味着当一个ClassLoader尝试加载某个类时,它首先会将任务委托给其父ClassLoader。如果父ClassLoader找不到该类,子ClassLoader才会尝试自己去加载。这个机制保证了系统类(如`java.lang.Object`)只被加载一次,...

    tomcat 类加载机制 —— ClassLoader

    类加载遵循“双亲委托模型”,即当一个类加载器收到加载类的请求时,它会首先委托父类加载器尝试加载,只有当父类加载器无法找到对应的类时,才会自己尝试加载。这样保证了基础类库的一致性,同时也允许Web应用覆盖...

    自定义classloader的使用

    Java的类加载机制遵循双亲委派模型,即当一个类加载器需要加载类时,它首先委托父类加载器尝试加载,只有当父类加载器无法加载时,才会尝试自己加载。这种设计避免了类的重复加载,并确保了核心类库的唯一性。 二、...

    ClassLoader小例子

    - Java的类加载机制遵循“双亲委派模型”,即一个类加载请求会先由顶级的Bootstrap ClassLoader处理,如果没有找到,则交给Extension ClassLoader,再未找到则继续交给App ClassLoader,最后是用户自定义的...

    ClassLoader 详解.doc

    在类加载过程中,遵循“双亲委派模型”:当一个类加载器需要加载某个类时,它首先会委托它的父加载器尝试加载,只有当父加载器无法加载时,当前加载器才会尝试自己加载。这种机制避免了类的重复加载,并确保了核心...

    java自定义类加载classloader文档,包括代码

    Java类加载器遵循双亲委派模型(Parent Delegation Model),即每个类加载器在尝试加载一个类之前,都会先委托给父加载器进行加载。如果父加载器能够成功加载,则返回;否则再由子加载器继续加载。 #### 五、自定义...

    ClassLoaderDemo.7z

    每个类在JVM中都只有一个实例,由某个ClassLoader加载。 **2. 双亲委托模型** Java的类加载机制遵循双亲委托模型,也称为线性递归模型。当一个类加载器收到加载类的请求时,它首先会将任务委托给其父类加载器,直到...

    java ClassLoader机制及其在OSGi中的应用

    在该模型下,当一个ClassLoader收到加载类的请求时,它首先会委托父加载器去尝试加载,只有当父加载器无法加载时,当前加载器才会尝试自己加载。这样设计避免了类的重复加载,并确保了核心类库的唯一性。 四、...

    Java ClassLoader Tutorial.zip

    Bootstrap ClassLoader加载JDK核心类库,Extension ClassLoader加载扩展类库,而AppClassLoader则加载应用类路径上的类。 3. 双亲委派模型:Java的类加载机制遵循双亲委派模型,即当一个类加载器接收到加载类的请求...

    classloader

    这个模型规定,当一个类加载器收到加载类的请求时,它首先会委托父类加载器尝试加载,只有当父类加载器无法加载时,才会自己尝试加载。这样可以保证类的唯一性,避免不同加载器加载相同类导致的问题。 综上所述,类...

    关于Classloader的总结!loadClass的分析和加载细节的分析

    Java中的类加载器通常遵循双亲委托模型。当一个类加载器接收到加载类的请求时,它首先会委托给其父类加载器尝试加载,只有当父类加载器无法加载时,才会尝试自己加载。这种设计确保了类的唯一性,防止了类的重复...

    ClassLoader的 一些测试

    当一个类加载器接收到加载类的请求时,它首先会委托给父类加载器加载,只有当父类加载器无法加载时,才会尝试自己加载。这样设计可以保证核心库的安全性,防止用户自定义类覆盖JDK的内置类。 自定义ClassLoader是一...

    ClassLoader原理

    Java的类加载过程遵循双亲委托模型,即一个类加载请求会先委托给父ClassLoader,只有当父类加载器无法完成加载时,才会由当前类加载器进行加载。 ClassLoader的工作流程可以分为三个主要步骤: 1. **查找**:当...

Global site tag (gtag.js) - Google Analytics