ClassLoader简介

本文详细介绍了Java类加载器的工作原理及其层次结构,包括引导类加载器、扩展类加载器和应用程序类加载器的作用及相互之间的关系。同时,通过实例说明了类加载过程中可能出现的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

      Java程序就是在Java虚拟机(JVM)中执行.class文件。但是所有的class文件并不是在程序一开始就把所有的class文件都加载到Java虚拟机(JVM)中,而是在需要的时候动态加载。这就需要类加载器了。

      类加载器,顾名思义就是负责把java类(class文件)加载到Java虚拟机(JVM)中。

      当启动JVM的时候,可以使用三个类加载器:引导(bootstrap)类加载器、扩展(extensions)类加载器、应用程序(application)类加载器(也称为系统类加载器)。这3个类加载器各自负责不同的类的加载并且有继承关系。

      1。引导(bootstrap)类加载器:它用来加载 Java 的核心库,是用原生代码来实现的,并不继承自 java.lang.ClassLoader。

      2。扩展类加载器负责加载扩展路径下的代码,一般位于<JAVA_HOME>/jre/lib/ext 或者通过java.ext.dirs 这个系统属性指定的路径下的代码。这个类加载器是由sun.misc.Launcher$ExtClassLoader 实现的。

      3。应用程序类加载器负责加载java.class.path(映射系统参数 CLASSPATH的值) 路径下面的代码,这个类加载器是由 sun.misc.Launcher$AppClassLoader 实现的。

 

      当处理类加载器时,父委托模式是一个需要理解的关键概念。它规定:类加载器在加载自己的类之前,必须委托父类加载器加载。父类加载器可以是客户化的类加载器或者引导类加载器。但是有一点很重要,类加载器只能委托自己的父类加载器,而不能是子类加载器(只能向上不能向下)。

      引导类加载器是所有类加载器的基类。

      引导类加载器 加载 扩展类加载器 ,扩展类加载器  加载 应用程序类加载器。

      结构图如下:

 类加载器结构图

      如果应用程序类加载器需要加载一个类,它首先委托扩展类加载器,扩展类加载器再委托引导类加载器。如果父类加载器不能加载类,子类加载器就回在自己的库中查找这个类。基于这个特性,类加载器只负责它的祖先无法加载的类。

      例如:现在有3个类 Test1,Test2,Test3

 

如果这3个都在默认的应该程序的路径下,允许没有问题。但是如果把Test2打包jar放到<javaHome>/jre/lib/ext目录下,允许Test2就会报错,找不到Test3类。

t2.classloeader = sun.misc.Launcher$ExtClassLoader@13f5d07
Exception in thread "main" java.lang.NoClassDefFoundError: Test3
        at Test2.main(Test2.java:17)
Caused by: java.lang.ClassNotFoundException: Test3
        at java.net.URLClassLoader$1.run(URLClassLoader.java:200)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
        at sun.misc.Launcher$ExtClassLoader.findClass(Launcher.java:229)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:252)
        at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:320)
        ... 1 more

 

为什么呢?Test3明明在应用程序目录下,怎么还找不到呢。其实这个类的加载机制决定的。我们运行Test2的时候,允许的是 应该程序类加载器,它首先会调用父的类加载器来加载Ttest2,即 用 扩展类加载器来加载Test2,扩展类加载器同样调用 父的类加载器(启动类加载器)加载Test2。启动类加载器没有加载到Test2,返回给 扩展类加载器来加载Test2。扩展类加载器在<javaHome>/jre/lib/ext目录下找到了Test2,加载。现在,当一个类已经被类加载器加载后,这个类需要的任何其他的新类都 必须用同一个类加载器加载他们(或者遵循父委托模式,由父类加载器加载)。Test2去访问Test3时候,听过扩展类加载器和父的引导类加载器都找不到Test3,所以java.lang.NoClassDefFoundError出现了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值