The problem is that I do not even know what exactly I should search for on google, so that's why I am asking for a short explanation here on SO.
您要搜索的是“类加载器”。这种类型的对象负责加载 Java 类。JVM 加载的每个类都由其完全限定名称和加载它的类加载器实例标识。这意味着在单个 JVM 中,您可以有几个完全命名为“com.example.Test”的类,每个类都由不同的类加载器加载——并且每个类都有自己的静态字段。更重要的是,这些类在运行时会被认为是不同的:将“com.example.Test”从一个类加载器转换为“com.example.Test”从某个其他类加载器会以 ClassCastException 结束。
为了避免多次加载多个公共类(如 java.util.List)的情况,类加载器通常保持在一个干净的层次结构中。每个类加载器都知道它的“父类”,即负责加载“更通用的类”的类加载器。当我们尝试加载一个类(通常是“按名称”发生)时,例如“com.example.OtherTest”,当前类加载器会尝试询问其父级是否能够加载它(然后父级依次询问其父级) , 等等)。这样,每个类都由能够加载它的最通用的类加载器加载(java.lang.String 将始终由标准引导类加载器加载,即使其他一些类加载器有一些不同的版本可用)。
当你部署一个战争时,glassfish 会为它创建一个单独的类加载器。类加载器知道如何从 WEB-INF/lib 和 WEB-INF/classes 加载类。它的父级是(或至少是祖父级)域类加载器,适用于所有应用程序。因此,在应用程序类加载器加载任何类之前 - 它会要求 Glassfish 执行此操作。
整个过程是相当可配置的,并且使您可以将一个通用库的副本加载到 JVM 中(例如,如果您将库放入 - AFAIR - domain1/lib/ext,它们将可供域类加载器使用,域类加载器是每个应用程序的类加载器;或者您甚至可以将它放在 JRE 的 lib/ext 文件夹中,并使其可用于主类加载器,这将为您运行的任何应用程序加载类)。在这种情况下,它们将共享静态字段。或者你可以让你的库由战争类加载器加载,并将所有静态字段“私有”给你的应用程序。