当前位置: 代码迷 >> 综合 >> corejava-笔记——类加载器&双亲委托机制
  详细解决方案

corejava-笔记——类加载器&双亲委托机制

热度:78   发布时间:2024-02-13 15:45:50.0

类加载器

Java中的类,想要运行就必须把类对应的class文件加载到内存,JVM中真正负责加载class文件内容的是类加载器

javaSE-API中,有一个类:java.lang.ClassLoader,他就是JVM中的类加载器

JVM启动后,默认会有的四种类加载器:

  • 启动类加载器(bootstrapClassLoader,非java语言实现,c++实现的)
    作用:加载指定路径中jar里面的class文件
    路径1:C:\Program Files\Java\jdk1.8.0_74\jre\lib\
    路径2:C:\Program Files\Java\jdk1.8.0_74\jre\classes\ ( 如果有这个目录的话)
    例如:rt.jar

  • 拓展类加载器(ExtClassLoader,Java语言实现,是ClassLoader类型的对象)
    作用:加载指定路径中jar里面的class文件(只能是jar中存在的class)
    路径:C:\Program Files\Java\jdk1.8.0_74\jre\lib\ext\
    例如:ext中默认存在的jar,或者用户放到ext目录下的jar包

  • 应用类加载器(AppClassLoader,Java语言实现,是ClassLoader类型的对象)
    作用:加载指定路径中class文件或者jar里面的class文件
    路径:CLASSPATH中配置路径,这个是用户自己配置的
    例如:.:bin:hello.jar

  • 自定义类加载器:开发人员自己写的

我们最常使用的就是应用类加载器,因为它可以通过CLASSPATH中的路径,去加载程序员自己编写的class文件到内存中

我们也可以把自己最常用的jar包(注意这里是jar包不是单个class文件哦),放到ext目录中,让拓展类加载器去自动加载这个jar中的class文件到内存,这样我们的代码就可以直接使用到这个jar中的类了(这个方法可以使用但是不推荐

但是,大多数情况下,即使我们需要用到其他jar中的代码,也一般会把jar中所有的路径配置到CLASSPATH中,让应用类加载器进行加载,这样会更加方便统一管理项目中使用的所有的jar

关于启动类加载器,他不是Java语言编写的,我们一般不要去动它的路径或者jar,他是负责在JVM启动的时候,吧JRE环境中最重要的一些library加载到内存,一旦出问题,JVM就无法正常运行

在这里插入图片描述

双亲委托机制

JDK默认的类加载机制,并非强制。(可以修改)

多个类加载器之间共同协作,然后把需要使用或运行的类加载到内存去执行,他们直接共同合作的方式就是双亲委托机制。

例:java com.test.demo.Hello命令

  • 当前要加载Hello.class文件中的类
  • 首先加载任务交给应用类加载器
  • 然后应用类加载器把任务委托给自己的父加载器(拓展类加载器)
  • 拓展类加载器把任务委托给自己的父加载器(启动类加载器)
  • 启动类加载器尝试去加载这个类,但是在指定路径下并没有找到
  • 然后任务有交回给拓展类加载器,拓展类加载器尝试加载这个类,但是在指定路径中没找到
  • 任务又交回给应用类加载器
  • 最后应用类加载器从CLASSPATH中指定的路径里面找到并加载了这个类,完成类加载的过程

在这里插入图片描述

思考:JavaSE-API中已经提供了一个类java.lang.System的类,如果我们也编写一个类加做System,同时指定它在java.lang包下面,那么这个时候我们是否能使用自己编写的java.lang.System类来代替JavaSE-API中的java.lang.System类?

不可以。因为当加载自己编写的java.lang.System的时候,内存中已经加载了jdk自带的java.lang.System(rt.jar),自己写的就不会再被加载