我最近在一次采访中被问及加载类时调用类加载器的顺序。
不幸的是,我从来不需要编写自己的类加载器,所以当时不熟悉类加载的复杂性。
这让我想知道,他们编写自己的类加载器的原因是什么。
所以这就是我的问题:人们面临哪些需要编写自己的类加载器的场景?
我最近在一次采访中被问及加载类时调用类加载器的顺序。
不幸的是,我从来不需要编写自己的类加载器,所以当时不熟悉类加载的复杂性。
这让我想知道,他们编写自己的类加载器的原因是什么。
所以这就是我的问题:人们面临哪些需要编写自己的类加载器的场景?
我目前正在开发一个高度模块化的超大型应用程序,即它由数百个 JAR 文件组成。这意味着 classpath 字符串变得巨大,导致各种地方出现各种问题,因为各种开发工具无法处理 5KB 的 classpath 字符串。这是通过编写一个从文件中读取其类路径的自定义类加载器来解决的。
典型的原因是您的应用程序托管了其他应用程序,这些应用程序在同一运行时(例如 Tomcat)中使用不同版本的相同库。因此,您必须确保您的类加载器可以为每个应用程序提供同一类的不同版本。
编辑:
为了澄清这一点(见评论中的混淆):当说“你的类加载器”时,我提到“一个实现java.lang.ClassLoader
”而不是这样一个类的实例。实际上,这两种含义都是您的类加载器: Tomcat 人员实现了不同的ClassLoader
类,并且在运行时拥有更多实例……有关详细信息,请参阅相应的文档。
当他们不得不维护我的代码时,无聊和折磨我的同事的愿望。:)
有些地方实际上将类存储在数据库中(曾经有一些地方,不确定是否还有),并使用类加载器在运行时从数据库中获取类。
当我想从 .jar 文件中加载 .jar 文件中的类时,我不得不实现一个 ClassLoader(这是几年前的事,我敢肯定现在有工具可以为你做到这一点)。即,您可以将依赖项 .jar 文件放入一个 .jar 文件中。
但这是唯一一次,根据我的经验,编写自定义 ClassLoader 是一件非常罕见的事情。
我遇到了一篇文章,它讨论了为什么(非常简短地)OSGI 使用自定义类加载器。
看看这个问题。
您可以在不停机的情况下进行软件发布,就像 24x7 运行系统中的情况一样。
您可以从 JMX 编写自己的类加载器调用,并在运行时替换类文件。
我们有一个应用程序框架,该框架具有基于它的“静态绑定”应用程序。这意味着您需要为每个要运行的应用程序拥有一个 jvm 实例,这不仅不利于内存使用,而且意味着您无法拥有一个超级应用程序来启动各种应用程序,或者任何简单的(非进程间)正在运行的应用程序之间的通信。
由于整个事情是从 webstart 运行的(即使用一堆 jar 作为类路径),防止系统类加载器找到类的解决方案是偏移包。例如,如果您a.b.X
在应用程序 foo 中有一个类,那么它将在 jar 文件中作为foo/a/b/X.class
.
在我的上一份工作中,我们实现了一个可以具有“插件逻辑查询定义”的服务器。(客户端可以按名称调用查询,服务器查找该名称的注册查询并运行它)。
查询定义是 jar 中包含的代码和/或元数据。
jar 通过我们的控制台应用程序上传到服务器。
上传时(以及稍后服务器重新启动时),我们的框架将为 jar 创建一个类加载器,以将其加载到正在运行的服务器中。
我在 这里看到了一个很好的帖子。它讨论了不同的类加载器、类加载器层次结构和自定义类加载器。
我曾经这样做过。我们必须使用第三方供应商提供的 API,而这个 API 使用了一个奇怪的 hibernate3.jar 版本。因此,我们必须使用自定义类加载器加载这个特定的 jar,以避免“串行版本 UID”异常。