原文: https://javatutorial.net/java-class-loaders-explained

本文介绍了 Java 类加载器的关键组件。

Java 类加载器是 Java 虚拟机(JVM)的重要组成部分。 它们用于加载类和接口。 Althaout 类装入器是 JVM 不可或缺的一部分,它们对于 Java 的内部工作非常重要,因此您在作为 Java 开发人员的日常工作中不太可能需要创建自定义类装入器。 例如,如果要创建将在诸如 Tomcat 之类的容器上执行的应用程序,则可以使用自定义类加载器的实际应用程序。 Tomcat 要做的是为每个 Web 应用程序创建一个类加载器(以便它以后可以卸载 Web 应用程序并释放内存)。

本文旨在解释类加载器的工作方式,并列出 Java 类加载器的关键组件。 您下次 Java 面试时可能会遇到有关类加载器的问题。

什么是 Java 类加载器

我们知道 Java 程序在 Java 虚拟机(JVM)上运行。 当我们编译 Java 类时,它将转换为平台和机器无关的字节码。 编译的类存储为.class文件。 当我们尝试使用类时,Java 类加载器将该类加载到内存中。 在已经运行的类中通过名称引用类时,这些类将引入 Java 环境。 一旦第一个类运行,以后将由类加载器完成加载类的尝试。 通常,通过声明并使用静态main()方法来完成第一类的运行。

Java 类加载器介绍 - 图1

类加载器的层次结构

Java 类加载器的类型

  1. 自举类加载器 - 它加载 JDK 内部类,通常加载rt.jar和其他核心类,例如java.lang.*包类
  2. 扩展类加载器 - 它从 JDK 扩展目录(通常是 JRE 的lib / ext目录)加载类。
  3. 系统类加载器 - 从系统类路径加载类,可以在使用-cp-classpath命令行选项调用程序时进行设置。

何时以及如何加载类

何时加载类? 确实有两种情况:

  1. 当执行新的字节码时(例如,MyClass mc = new MyClass()😉
  2. 当字节码静态引用一个类时(例如System.out)。

类加载器是分层的。 第一个类是在类中声明的静态main()方法的帮助下专门加载的。 所有随后加载的类均由已加载并正在运行的类加载。

进一步的类加载器在加载类时遵循以下规则:

  1. 检查该类是否已经加载。
  2. 如果未加载,请要求父类加载器加载该类。
  3. 如果父类加载器无法加载类,请尝试在该类加载器中加载它。

静态与动态类加载

使用 Java 的new运算符静态加载类。 动态加载是一种使用Class.forName()在运行时以编程方式调用类加载器的功能的技术。

loadClassClass.forName之间的区别

loadClass仅加载类,但不初始化对象,而Class.forName在加载对象后初始化对象。 例如,如果您使用ClassLoader.loadClass加载 JDBC 驱动程序,则该驱动程序将无法注册,并且您将无法使用 JDBC

java.lang.Class.forName(String className)方法返回与具有给定字符串名称的类或接口关联的Class对象。 如果找不到该类,则此方法引发ClassNotFoundException

下面的示例演示Class.forName的用法

  1. package net.javatutorial;
  2. import java.lang.reflect.Method;
  3. public class ClassForNameExample {
  4. public static void main(String[] args) {
  5. try {
  6. Class<?> c = Class.forName("java.awt.Point");
  7. System.out.println("name = " + c.getName());
  8. System.out.println("package = " + c.getPackage());
  9. Method[] methods = c.getDeclaredMethods();
  10. System.out.println("----- Class methods ---------------");
  11. for (Method method : methods) {
  12. System.out.println(method.getName());
  13. }
  14. } catch (ClassNotFoundException e) {
  15. e.printStackTrace();
  16. }
  17. }
  18. }

加载java.awt.Point类。 比我们打印类名称,包和该类所有可用方法的名称。 这是在 Java 8 中执行程序的结果:

  1. name = java.awt.Point
  2. package = package java.awt, Java Platform API Specification, version 1.8
  3. ----- Class methods ---------------
  4. equals
  5. toString
  6. getLocation
  7. getX
  8. getY
  9. setLocation
  10. setLocation
  11. setLocation
  12. move
  13. translate