gpt4 book ai didi

java - 如何控制哪个 ClassLoader 加载类?

转载 作者:塔克拉玛干 更新时间:2023-11-03 05:06:37 25 4
gpt4 key购买 nike

眼前的情况并不像标题所暗示的那么简单。

通过 JWS 运行的 Java 1.6_17。

我有一个类,比方说 MyClass ,它的一个实例成员变量是来自错误的第三方库的类型,在类初始化期间,它动态地尝试使用 加载它自己的一些类>Class.forName(字符串)。在其中一种情况下,它恰好动态调用:Class.forName("foo/Bar")。这个类名不遵循二进制名称的 JLS,最终导致 java .lang.NoClassDefFoundError: foo/Bar.

我们有一个自定义的 ClassLoader,我已将清理方法添加到 ClassLoader.findClass(String)ClassLoader.loadClass(String) 这解决了这个问题。

我可以这样调用:myCustomClassLoader.findClass("foo/Bar")

然后加载类没有任何问题。但是即使我提前加载了类,我仍然会在以后得到异常。这是因为在引用 BarMyClass 初始化期间 - 他们的 代码最终调用 Class.forName("foo/Bar") 在某处的静态 block 中。如果它尝试使用的 ClassLoader 是我的自定义类加载器,这实际上是可以的。但事实并非如此。 com.sun.jnlp.JNLPClassLoader 不执行此类清理,因此是我的问题。

我已确保将 Thread.currentThread().getContextClassLoader() 设置为我的自定义类加载器。但这(如您所知)没有效果。由于我阅读了一些内容,我什至将它设置为我在 main() 中做的第一件事,MyClass.class.getClassLoader() - 是 JNLPClassLoader。如果我可以强制它不是 JNLPClassLoader 而是使用我的,问题就解决了。

如何通过在类初始化期间进行的静态 Class.forName("foo/Bar") 调用来控制使用哪个 ClassLoader 来加载类?我相信如果我可以强制 MyClass.class.getClassLoader() 返回我的自定义类加载器,我的问题就会得到解决。

如果有人有想法,我愿意接受其他选择。

TL;DR: 帮我强制所有 MyClass 引用的第三方库中的 Class.forName(String) 调用 - 使用我选择的类加载器.

最佳答案

这让我想起了10年前读过的一篇关于Java类加载安排的文章。它还在那里on JavaWorld .

本文不会直接回答您的问题,但可能有助于理解您的问题。您需要使 MyClass 通过您的自定义类加载器加载并胜过默认的类加载行为,即首先将类加载委托(delegate)给父类加载器,并且仅在失败时才尝试加载类。

允许 MyClass 由您以外的类加载器加载将存储从实例化类到该类加载器的关系(通过 getClassLoader)并导致 Java 使用其他类加载器类加载器尝试发现任何引用的类 found at compile time ,凭借类加载器层次结构和委托(delegate)模型有效地绕过您的自定义类加载器。如果 MyClass 由您的类加载器定义,您将获得第二次机会。

这听起来像是 URLClassLoader 之类的工作,覆盖 loadClass 并胜过驻留在您的 JAR 中的类的委托(delegate)模型。您可能希望使用 Bootstrap 方法(如 Thomas 在上面的评论中所建议的那样)强制通过您的自定义类加载器加载单个入口点类,同时拖动所有其他入口点类。

同样提供信息的是 this other JavaWorld article由同一个人发出警告,警告您有关 Class.forName 的注意事项。这也可能会影响您的类加载安排。

我希望这会有所帮助并提供信息。无论如何,这听起来像是一个困难的解决方案,随着代码的发展很容易被破坏。

关于java - 如何控制哪个 ClassLoader 加载类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13925224/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com