• 深入浅出 Java 类加载机制!


    类加载器

    简单讲,类加载器ClassLoader的功能就是负责将class文件加载到jvm内存。

    类加载器分类

    从虚拟机层面讲分为两大类型的类加载器,一是Bootstrap Classloader即启动类加载器(C++实现),它是虚拟机的一部分,二是其他类型类加载器(JAVA实现),在虚拟机外部,并全部继承ClassLoader类。

    从细分的角度讲会分为以下三类类加载器:

    1、Bootsrap ClassLoader

    启动类加载器,完全由jvm控制加载,外面访问不到这个类加载器,即不能被java程序引用。它主要负责加载jvm自身的工作类,即java/lib目录和-Xbootclasspath参数指定的目录的类库。

    2、Extension ClassLoader

    扩展类加载器,由java实现,即ExtClassLoader实现类。它主要负责加载java/lib/ext目录和系统环境变量java.ext.dirs指定目录所有类库。

    3、Application ClassLoader

    应用程序类加载器,由java实现,即AppClassLoader实现类。它的父类是ExtClassLoader,它主要负责加载classpath目录上的类库。如果没有自定义ClassLoader,它就是程序中默认的ClassLoader,即可以通过ClassLoader.getSystemClassLoader()获取当前系统的类加载器。

    从上图看虽然Bootstrap ClassLoader是最顶层的类加载器,但是不能被程序引用,它也不是ExtClassLoader的父类加载器,ExtClassLoader没有父类载器,我们不防来看下面简单的例子。

    程序首先输出了程序默认的类加载器AppClassLoader,然后再输出了其父类加载器ExtClassLoader,然后就完了,这就证实了上面的理论。

    类加载机制

    虽然定义了上面这几个类加载器,但在加载时类加载器会审查一个class类应该由哪个类型的加载器负责加载,它使用的是等级加载机制,是一种双亲委派模型。

    双亲委派模式要求所有类加载器,除了顶层的Bootstrap类加载器之外都要有自己的父类加载器。在收到一个类加载请求时,当前默认的类加载器它不会首先自己来加载这个类,它会委托给自己的父类加载器去加载,父类加载器再委托给父父类加载器,以此类推,直到顶层类加载器,由上到下加载,除非上面的类加载器都无法加载时自己才去加载。

    来看看ClassLoader.loadClass方法源码

    再回到之前文章中的有一道关于是否可以自定义类java.lang.String并使用的面试题,它在java/lib目录下,所以当应用类加载器去classpath加载时会去委托父类加载器,这时最顶层类加载器会发现自己之前已经加载过,所以这次不再加载,所以自定义的这个java.lang.String虽然可以正常编译,但不能被类加载器加载并使用。

    所以,这也是双亲委派模式的好处,同一个路径的类保证不能加载两次,保证了类与类之间的正常行为和正常运行。

    推荐去我的博客阅读更多:

    1.Java JVM、集合、多线程、新特性系列教程

    2.Spring MVC、Spring Boot、Spring Cloud 系列教程

    3.Maven、Git、Eclipse、Intellij IDEA 系列工具教程

    4.Java、后端、架构、阿里巴巴等大厂最新面试题

    觉得不错,别忘了点赞+转发哦!

  • 相关阅读:
    编译并使用Lua语言
    C#中使用DLL文件
    将Unity3D游戏移植到Android平台上
    Unity3D知识点
    清下书柜,工作书,旧书,正版书,个人学习过的书asp,net,delphi,java,flex,actionscript,vb...
    使用ABP打造SAAS系统(2)——前端框架选择
    使用ABP打造SAAS系统(1)——环境准备
    延迟实例单例模式注意点
    jvm指令解释i = i++ + i++ + i++ + ++i;等于多少
    MYSQL增加库表权限
  • 原文地址:https://www.cnblogs.com/javastack/p/13050500.html
Copyright © 2020-2023  润新知