ClassLoader 的 findLoadedClass 方法

本文详细介绍了Java类加载器的findLoadedClass方法,该方法用于检查类是否已经被加载。在类加载过程中,首先加锁,然后调用findLoadedClass,若类已加载则返回Class对象,否则返回null。类加载分为主动和被动两种情况。对于被动加载,即使类实际由其他加载器加载,但只要初始请求加载的类加载器参与了加载过程,它也会被记录为初始加载器。这个机制在类的委派加载过程中起到关键作用。

findLoadedClass官方文档说明:

Returns the class with the given binary name if this loader has been recorded by the Java virtual machine as an initiating loader of a class with that binary name.

在ClassLoader的loadClass方法中第一步是去加锁,第二部就会调用findLoadedClass方法判断该类是否已经加载过,加载过就返回Class对象,未加载过就返回null,它有两种情况:
第一:
如果某个类是因为代码中主动加载的,那么只有加载该类的类加载器调用findLoadedClass方法才能找到,其它的类加载器调用此方法返回null。

第二:
如果某个类是因为被动加载的,比如现在有两个类A、B,其中B是A的父类,有两个类加载器AClassLoader、BClassLoader,A类在AClassLoader的加载路径下,B类在BClassLoader的加载路径下,BClassLoader是AClassLoader的父类加载器。
现在代码中主动调用AClassLoader去加载A类,而初始化一个子类会去判断父类是否加载,所以AClassLoader会去加载B类,而AClassLoader会委派给其父类加载器BClassLoader去加载,BClassLoader会委派到后面的父类省略,反正BClassLoader会加载成功B类。
这是时候虽然B类是由BClassLoader去加载成功的,但是调用AClassLoader的findLoadedClass也是能够找到B类的,因为B类是被动加载,是由AClassLoader加载A类,发现A的父类B类没有加载,然后AClassLoader又去加载B类,虽然B类最终不是AClassLoader加载的,但是AClassLoader会被标记为B类的初始类加载器。

Java 中的 `ClassLoader` 是用于动态加载类的抽象类,`loadClass` 是其核心方法之一,主要用于将类的字节码文件加载到 JVM 中,并返回对应的 `Class` 对象。该方法在类加载机制中起着至关重要的作用。 ### 作用 `loadClass` 方法的作用是根据类的全限定名加载类,其主要流程包括: - 检查类是否已经被加载。 - 如果未被加载,则尝试使用双亲委托机制加载类。 - 如果双亲无法加载类,则尝试由当前类加载器加载。 通过该方法,JVM 能够动态地将类加载到运行时环境中,使得 Java 应用可以在运行时加载和使用新的类。 ### 工作原理 `loadClass` 方法的默认实现遵循双亲委托模型,其基本流程如下: 1. **检查类是否已经加载**:JVM 会首先检查该类是否已经被加载到内存中,如果是,则直接返回已加载的 `Class` 对象。 2. **委托父类加载器加载**:如果类尚未加载,`ClassLoader` 会将加载请求委托给其父类加载器,逐层向上委托,直到引导类加载器(Bootstrap ClassLoader)。 3. **尝试自己加载类**:如果父类加载器无法加载该类(例如类不在其搜索路径中),当前类加载器将尝试自己加载类。 4. **调用 `findClass` 方法**:如果父类加载器无法加载类,则当前类加载器会调用自身的 `findClass` 方法来查找和加载类的字节码。 以下是 `loadClass` 方法的简化伪代码: ```java protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { // First, check if the class has already been loaded Class<?> c = findLoadedClass(name); if (c == null) { try { // Delegate to parent class loader if (parent != null) { c = parent.loadClass(name, false); } else { c = findBootstrapClassOrNull(name); } } catch (ClassNotFoundException e) { // ClassNotFoundException thrown if class not found // from the non-null parent class loader } if (c == null) { // Try to find the class using this class loader c = findClass(name); } } if (resolve) { resolveClass(c); } return c; } ``` ### 使用场景 `loadClass` 方法在以下场景中被广泛使用: - **动态加载类**:例如,在运行时根据需要加载特定的类,而不是在启动时加载所有类。 - **实现插件系统**:通过自定义 `ClassLoader`,可以在运行时加载插件模块的类。 - **隔离类的版本**:通过不同的类加载器加载相同类的不同版本,从而实现类的隔离。 - **热部署**:在不重启应用的情况下,重新加载类的定义。 在自定义类加载器时,如果直接覆盖 `loadClass` 方法而不调用父类加载器,可能会导致无法加载核心类库(如 `Object` 或 `String`),从而引发 `NoClassDefFoundError`。因此,在自定义 `ClassLoader` 时,应确保正确使用双亲委托机制,以避免类加载失败 [^3]。 ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值