URLClassLoader 是 Java 中的一个类加载器,用于从指定的 URL 路径加载类和资源。
URLClassLoader 继承自 ClassLoader 类,具有以下特点和用途:
动态加载类:可以在运行时从指定的 URL 位置(如文件系统路径、网络路径等)加载类文件,实现动态扩展应用的功能。
加载资源:不仅可以加载类,还能加载相关的资源文件(如配置文件、图像等)。
自定义类加载逻辑:通过扩展 URLClassLoader ,可以实现自定义的类加载策略和规则。
以下是一个简单的示例,展示如何创建 URLClassLoader 并加载类:
package com.hxstrive.jdk7.urlclassloader; import java.net.URL; import java.net.URLClassLoader; /** * URLClassLoader 类 * @author hxstrive.com */ public class UrlClassLoaderDemo1 { public static void main(String[] args) throws Exception { URL jarUrl = new URL("file:///D:\\mysql-connector-java-8.0.18.jar"); try { // 创建 URLClassLoader 对象 URLClassLoader urlClassLoader = new URLClassLoader(new URL[]{ jarUrl }); // 加载类 Class<?> clazz = urlClassLoader.loadClass("com.mysql.jdbc.Driver"); System.out.println(clazz); //class com.mysql.jdbc.Driver } catch (Exception e) { e.printStackTrace(); } } }
URLClassLoader 和 ClassLoader 有以下一些区别:
区别分类 | ClassLoader | URLClassLoader |
功能特定性 | 是一个抽象类,定义了类加载的基本框架和方法 | 是 ClassLoader 的一个具体实现,专门用于从指定的 URL 位置加载类和资源。 |
加载来源 | 加载来源较为通用和抽象,具体的子类决定从何处获取类和资源 | 明确地从指定的 URL 路径获取 |
配置灵活性 | 本身的配置相对较为复杂,通常需要其子类来具体实现和扩展 | 可以通过提供 URL 数组来简单直观地指定加载的位置。 |
适用场景 | 适用于需要自定义复杂类加载逻辑的情况 | 更适用于基于 URL 路径进行类和资源加载的相对简单和直接的场景 |
例如,如果您的应用需要从特定的网络位置或文件系统路径动态加载类和资源,使用 URLClassLoader 会比较方便直接。但如果需要更精细和复杂的类加载控制,可能需要自定义一个继承自 ClassLoader 的类来实现特定的逻辑。
在 Java7 之前,URLClassLoader 在某些情况下可能会导致资源泄露。这通常是由于没有正确地释放或关闭相关的资源所引起的。例如,如果在使用完 URLClassLoader 后,没有调用其 close 方法来释放相关的资源(如打开的文件、网络连接等),就可能导致资源一直被占用,无法被其他部分的程序使用,从而造成资源泄露。
另外,如果在加载类或资源的过程中,创建了一些临时对象或打开了一些外部资源,但没有进行适当的清理和释放,也可能引发资源泄露问题。
为了避免资源泄露,应当在使用完 URLClassLoader 后,及时调用其 close 方法来确保相关资源得到正确释放。
在 Java7 中,URLClassLoader 类实现了 AutoCloseable 接口,添加了一个用来关闭该类加载器的 close() 方法。如下图:
因此你可以使用 try-with-resources 语句来自动释放资源,例如:
package com.hxstrive.jdk7.urlclassloader; import java.net.URL; import java.net.URLClassLoader; /** * URLClassLoader 类 * @author hxstrive.com */ public class UrlClassLoaderDemo2 { public static void main(String[] args) throws Exception { URL jarUrl = new URL("file:///D:\\mysql-connector-java-8.0.18.jar"); // 创建 URLClassLoader 对象 try(URLClassLoader urlClassLoader = new URLClassLoader(new URL[]{ jarUrl })) { // 加载类 Class<?> clazz = urlClassLoader.loadClass("com.mysql.jdbc.Driver"); System.out.println(clazz); //class com.mysql.jdbc.Driver } catch (Exception e) { e.printStackTrace(); } } }
⚠️小心:不要在类加载器关闭后使用任何的类。否则,如果那些类需要加载其他的类,那么它们将加载失败。