栏目分类:
子分类:
返回
文库吧用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
文库吧 > IT > 软件开发 > 后端开发 > Java

JAVA 类加载器

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

JAVA 类加载器

类加载器

 

在 java 中,类基于按需加载,所有的类都是使用类加载器进行加载,就是将 .class 文件加载到内存。JVM 中内置了三个类加载器,分别是:启动类加载器,扩展类加载器,应用类加载器。除了启动类加载器之外,其他的 JAVA 实现的类加载器都是继承 java.lang.ClassLoader。

  • 启动类加载器:最顶层的加载类,使用 C++ 实现。负责加载 %JAVA_HOME%/lib 目录下的 jar 包和类或者被 -Xbootclasspath 参数指定的路径中的所有类;
  • 扩展类加载器:主要负责加载 %JRE_HOME%/lib/ext 目录下的 jar 包和类,或被 java.ext.dirs 系统变量所指定的路径下的 jar 包;
  • 应用类加载器:面向我们用户的加载器,负责加载当前应用 classpath 下的所有 jar 包和类。
类加载器关系

每个类加载都有一个父类加载器,通过下面的程序来验证。

public class ClassLoaderDemo {
    public static void main(String[] args) {
        System.out.println("ClassLodarDemo's ClassLoader is " + ClassLoaderDemo.class.getClassLoader());
        System.out.println("The Parent of ClassLodarDemo's ClassLoader is " + ClassLoaderDemo.class.getClassLoader().getParent());
        System.out.println("The GrandParent of ClassLodarDemo's ClassLoader is " + ClassLoaderDemo.class.getClassLoader().getParent().getParent());
    }
}
ClassLodarDemo's ClassLoader is sun.misc.Launcher$AppClassLoader@18b4aac2
The Parent of ClassLodarDemo's ClassLoader is sun.misc.Launcher$ExtClassLoader@1b6d3586
The GrandParent of ClassLodarDemo's ClassLoader is null

AppClassLoader 的父类加载器为 ExtClassLoader, ExtClassLoader的父类加载器为 null,null 并不代表 ExtClassLoader 没有父类加载器,而是 BootstrapClassLoader 。

双亲委派模型

虚拟机在加载类的时候,首先会判断该类是否被加载过,如果被加载过则直接返回,否则会尝试加载类。加载的时候会寻找父类加载器的 classLoad() 函数处理,因此所有的请求最终都会发送到顶层的启动类加载器中。当父类无法处理的时候才会交由自己处理。当父类加载器为 null 时,会使用启动类加载器 BootstrapClassLoader 作为父类加载器。这种机制称为双亲委派。委派的过程可以分为三个步骤:

  • 收到类加载的请求之后,类加载器不会加载类,将这个请求委派其父类加载器;
  • 如果父类加载器还存在父类加载器,则进一步向上委托,依次向上,最终会到达启动类加载器;
  • 如果父类加载器可以加载就完成加载任务成功返回,倘若不能加载,子类才尝试去加载。

例子说明机制

自行创建 java.lang 包,在其目录下创建 String 类,增加 main 函数执行。

package java.lang;

public class String {

  public static void main(String[] args) {
    System.out.println("hello world");
  }
}

出现了 在类 java.lang.String 中找不到 main 方法。

错误: 在类 java.lang.String 中找不到 main 方法, 请将 main 方法定义为:
   public static void main(String[] args)
否则 JavaFX 应用程序类必须扩展javafx.application.Application

由于 String 类在 java.lang 包下,在申请加载 String 类时,加载类会请求其父类加载器加载,会直接请求启动类加载器,启动类加载器从 java.lang 中发现了 String 类,并将其加载返回。但是此 String 并非自定义的 String, 该类没有 main 入口,因此出现该异常。

双亲委派好处

双亲委派模型保证了 Java 程序的稳定运行,可以避免类的重复加载(JVM 区分不同类的方式不仅仅根据类名,相同的类文件被不同的类加载器加载产生的是两个不同的类),也保证了 Java 的核心 API 不被篡改。如果没有使用双亲委派模型,而是每个类加载器加载自己的话就会出现一些问题,比如我们编写一个称为 java.lang.Object 类的话,那么程序运行的时候,系统就会出现多个不同的 Object 类。

转载请注明:文章转载自 www.wk8.com.cn
本文地址:https://www.wk8.com.cn/it/1040796.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 wk8.com.cn

ICP备案号:晋ICP备2021003244-6号