{"blogColumn":{"blogSum":0,"id":1,"imageType":"png","name":"语言基础"},"blogTagList":[{"blogSum":0,"id":1,"name":"Java"},{"blogSum":0,"id":3,"name":"JVM"}],"content":"

2. 类加载器 Class Loader

\n

2.1 类加载器的作用

\n

Java 虚拟机对 class 文件采用的是按需加载的方式。也就是说,我们所编写的 .java 文件被编译成 .class 文件后,只有当需要使用该类时,JVM 才会将它的 .class 文件加载(Load)到内存中生成 class 对象,然后通过链接(Link)将类的二进制数据合并到 JRE 中,最后将类的静态变量初始化(Initialize)为正确的值。

\n

类加载器负责加载所有的类,其为所有被载入内存中的类生成一个 java.lang.Class 类的实例对象。一旦一个类被加载进 JVM 中,同一个类就不会被再次载入了。

\n

此外,正如一个对象有一个唯一的标识一样,一个载入 JVM 的类也有一个唯一的标识。在 Java 中,一个类用其全限定类名(包名 + 类名)作为标识;但在 JVM 中,一个类由其全限定类名和其类加载器一同作为唯一标识

\n

类加载的具体过程如下:

\n\n

2.2 类加载器的分类

\n

JVM 中三种预置的类加载器自顶向下可依次分为:

\n
    \n
  1. 引导类加载器(Bootstrap ClassLoader):它用来加载 Java 的核心类,负责加载 $JAVA_HOME中jre/lib/rt.jar 里所有的 .class 文件,是用原生 C++ 代码来实现的,并不继承自 java.lang.ClassLoader。由于引导类加载器涉及到虚拟机本地实现细节,开发者无法直接获取其引用,所以不允许直接通过引用进行操作。
  2. \n
  3. 扩展类加载器(Extension ClassLoader):它负责加载 JRE 的扩展目录 lib/ext 或者由 java.ext.dirs 系统属性指定的目录中的 JAR 包的类。它由 Java 语言实现,上层加载器为引导类加载器。
  4. \n
  5. 系统类加载器(Application ClassLoader):也称为应用类加载器,它负责在 JVM 启动时加载来自 Java 命令的 -classpath 选项、java.class.path 系统属性,或者 CLASSPATH 环境变量所指定的 JAR 包和类路径。程序可以通过 ClassLoader 的静态方法 getSystemClassLoader() 来获取系统类加载器。由 Java 语言实现,上层加载器为拓展类加载器。
  6. \n
\n

除此之外,我们还可以使用自定义类加载器(即继承自 ClassLoader 抽象类的类)。严格来讲,类加载器只分为引导类加载器自定义类加载器两类,因为拓展类加载器和系统类加载器都继承自 ClassLoader 抽象类,而引导类加载器是通过 C 语言实现的。

\n

当然,我们也可以自己编写类去继承 ClassLoader 抽象类。如果没有特别指定,则用户自定义的类加载器都以系统类加载器作为上层加载器。

\n

2.3 双亲委派机制

\n

JVM 在加载某个类的 class 文件时,采用的是双亲委派机制,即把请求委派给父类处理。这是一种任务委派模式,该模式的具体工作流程如下:

\n\n

简而言之,其核心思想可以概括成一句话:“向上委派,向下加载。”

\n

现在思考一个问题:当我们自己创建一个 String 类,并将它放在我们自己创建的 java.lang 包下时,会发生什么呢?

\n\n

通过上面的例子,我们可以得知,双亲委派机制可以避免类的重复加载,同时还可以防止核心 API(诸如 String 类)被随意篡改

\n","createTime":"2021-09-20 03:38:18","id":50,"redisKeyWithId":"mxblog:view:blog:50","shield":{"id":1,"name":"正常"},"summary":"Java 虚拟机对 class 文件采用的是按需加载的方式。也就是说,我们所编写的 .java 文件被编译成 .class 文件后,只有当需要使用该类时,JVM 才会将它的 .class 文件加载到内存中生成 class 对象,然后通过链接将类的二进制数据合并到 JRE 中,最后将类的静态变量初始化为正确的值。类加载器负责加载所有的类,其为所有被载入内存中的类生成一个 java.lang.Class 类的实例对象。一旦一个类被加载进 JVM 中,同一个类就不会被再次载入了。此外,正如一个对象有一个唯一的标识一样,一个载入 JVM 的类也有一个唯一的标识,由它的全限定类名和其类加载器一同组成。","title":"JVM(二) 类加载器","type":{"id":1,"name":"原创"},"user":{"avatarType":"png","email":"3297705066@qq.com","id":1,"username":"妙霄"},"views":125}