Java 中的 ClassLoader17 Mar 2025 | 5 分钟阅读 Java ClassLoaderJava ClassLoader 是一个抽象类。它属于 java.lang 包。它从不同的资源加载类。Java ClassLoader 用于在运行时加载类。换句话说,JVM 在运行时执行链接过程。类根据需要加载到 JVM 中。如果一个已加载的类依赖于另一个类,那么该类也会被加载。当我们请求加载一个类时,它会将该类委托给其父类加载器。这样,在运行时环境中就维护了唯一性。这对于执行 Java 程序至关重要。 ![]() Java ClassLoader 基于三个原则:委派(Delegation)、可见性(Visibility) 和 唯一性(Uniqueness)。
ClassLoader 的类型在 Java 中,每个 ClassLoader 都有一个预定义的加载类文件的位置。Java 中有以下几种 ClassLoader 类型: Bootstrap Class Loader(启动类加载器): 它从 rt.jar 加载标准的 JDK 类文件和其他核心类。它是所有类加载器的父类。它没有父类。当我们调用 String.class.getClassLoader() 时,它返回 null,任何基于它的代码都会抛出 NullPointerException。它也称为 Primordial ClassLoader。它从 jre/lib/rt.jar 加载类文件。例如,java.lang 包中的类。 Extensions Class Loader(扩展类加载器): 它将类加载请求委托给其父类加载器。如果类加载不成功,它会从 jre/lib/ext 目录或 java.ext.dirs 指定的任何其他目录加载类。它在 JVM 中由 sun.misc.Launcher$ExtClassLoader 实现。 System Class Loader(系统类加载器): 它从 CLASSPATH 环境变量加载应用程序特定的类。它可以在调用程序时使用 -cp 或 classpath 命令行选项进行设置。它是 Extension ClassLoader 的子类。它由 sun.misc.Launcher$AppClassLoader 类实现。所有 Java ClassLoader 都实现了 java.lang.ClassLoader。 ![]() Java ClassLoader 的工作原理当 JVM 请求加载一个类时,它会调用 java.lang.ClassLoader 类的 loadClass() 方法,并传入类的完全限定名。loadClass() 方法会调用 findLoadedClass() 方法来检查该类是否已经被加载。这是为了避免多次加载同一个类。 如果类已经被加载,它会将请求委托给父 ClassLoader 来加载。如果 ClassLoader 找不到该类,它会调用 findClass() 方法在文件系统中查找类。下图展示了 ClassLoader 在 Java 中如何使用委派机制加载类。 ![]() 假设我们有一个应用程序特定的类 Demo.class。加载这个类文件的请求会传递给 Application ClassLoader。它会将请求委托给它的父类 Extension ClassLoader。然后,它会委托给 Bootstrap ClassLoader。Bootstrap ClassLoader 在 rt.jar 中搜索该类,但发现它不在那里。现在,请求会转给 Extension ClassLoader,它会在 jre/lib/ext 目录中搜索,并尝试在那里找到该类。如果类在那里找到,Extension ClassLoader 就会加载该类。Application ClassLoader 根本不会加载该类。当 Extension ClassLoader 无法加载该类时,Application ClassLoader 才会从 Java 的 CLASSPATH 中加载它。 可见性原则规定,子类加载器可以看到父类加载器加载的类,但反之则不然。这意味着,如果 Application ClassLoader 加载了 Demo.class,那么尝试使用 Extension ClassLoader 显式加载 Demo.class 就会抛出 java.lang.ClassNotFoundException。 根据唯一性原则,父类加载器加载的类不应该被子类加载器再次加载。因此,可以编写一个违背委派和唯一性原则的类加载器,并自行加载类。 总之,类加载器遵循以下规则:
考虑以下示例 使用以下命令编译并运行上述代码: -verbose:class: 它用于显示 JVM 加载的类的相关信息。当动态加载类时,它很有用。下图显示了输出。 ![]() 我们可以观察到,应用程序类(Demo)所需的运行时类首先被加载。 何时加载类只有两种情况:
静态类加载与动态类加载类是使用 "new" 运算符进行静态加载的。动态类加载是通过使用 Class.forName() 方法在运行时调用类加载器的函数来实现的。 loadClass() 和 Class.forName() 之间的区别loadClass() 方法仅加载类,但不初始化对象。而 Class.forName() 方法在加载类之后初始化对象。例如,如果您使用 ClassLoader.loadClass() 来加载 JDBC 驱动程序,类加载器不允许加载 JDBC 驱动程序。 java.lang.Class.forName() 方法使用给定的字符串名称返回与该类或接口关联的 Class 对象。如果找不到类,它会抛出 ClassNotFoundException。 示例在这个例子中,加载了 java.lang.String 类。它打印类名、包名以及 String 类所有可用方法的名称。我们在以下示例中使用 Class.forName()。 Class<?>: 表示一个 Class 对象,它可以是任何类型(? 是一个通配符)。Class 类型包含关于类的元信息。例如,String.class 的类型是 Class<String>。如果被建模的类未知,则使用 Class<?>。 getDeclaredMethod(): 返回一个 Method 对象数组,这些对象反映了此 Class 对象表示的类或接口的所有声明的方法,包括公共、受保护、默认(包)访问和私有方法,但不包括继承的方法。 getName(): 它以 String 的形式返回此 Method 对象所表示的方法名称。 输出 Class Name: java.lang.String Package Name: package java.lang -----Methods of String class ------------- value coder equals length toString hashCode getChars ------ ------ ------ intern isLatin1 checkOffset checkBoundsOffCount checkBoundsBeginEnd access$100 access$200 下一个主题Java 教程 |
java.text.FieldPosition 类包含 getEndIndex() 函数。要查找 FieldPosition 对象中位于最后一个字符之前的字符的索引,请使用 FieldPosition 类。语法:public int getEndIndex() 参数:此方法不接受任何参数。返回值:字符...
阅读 2 分钟
在 Java 中,旅行商问题(TSP)是一个需要找到一条最短路线,该路线恰好经过每个城市一次并返回到起点的问题。哈密顿回路(Hamiltonian Cycle)是 Java 中的另一个问题,与 TSP 非常相似。它们之间的主要区别在于 TSP...
阅读 4 分钟
数组划分问题涉及将数组分成两个子集,使得它们之和的差最小化。这个问题是划分问题的经典示例,在负载均衡、公平分配和优化任务中都有应用。使用递归和记忆化使用动态规划 每个...
阅读 6 分钟
Java 中的实时聊天应用程序是指能够让多个用户同时向其他人发送消息并接收其消息的能力。此类应用程序通常采用客户端-服务器系统,其中服务器处理客户端之间的通信。要创建基本的聊天应用程序,...
7 分钟阅读
在 Java 中,当字符前面有一个反斜杠(\)时,它被称为 Java 转义序列或转义字符。请记住,转义序列必须用双引号("")括起来。它们用于表示难以或不可能直接表示的字符...
阅读 4 分钟
Giuga 数是一个合数 N,它具有一个独特的属性。该属性指出,对于 N 的每个素数因子 p,N 除以 p 减 1((N/p) - 1)也必须能被 p 整除。如果一个数 N 满足这个条件...
5 分钟阅读
在 Java 中,继承使一个类能够采用另一个类的行为和功能。从中继承功能和行为的类被称为基类、父类或超类。接收类通常被称为子类,...
阅读 4 分钟
Java 是一种强大且通用的编程语言,它提供了许多工具和库,可以帮助企业解决复杂的挑战。其中一项挑战涉及解决商业板问题,这需要高效的算法和数据结构来优化决策过程。在本节中,我们将探讨如何...
阅读 6 分钟
Amazon Web Services (AWS) 提供了许多服务,使企业能够在云中开发、部署和管理应用程序和基础设施。监控这些资源以确保它们可靠高效地运行非常重要。AWS CloudWatch 是一种监控服务,它收集和跟踪...
5 分钟阅读
Java 是一种通用且广泛使用的编程语言,它为构建各种数据结构和类提供了坚实的基础。在本节中,我们将深入探讨一个名为 Cint 的自定义类,它表示一个可比较的整数,并提供额外的比较操作功能。Java Cint 类 Java Cint...
5 分钟阅读
我们请求您订阅我们的新闻通讯以获取最新更新。
我们提供所有技术(如 Java 教程、Android、Java 框架)的教程和面试问题
G-13, 2nd Floor, Sec-3, Noida, UP, 201301, India