【问题标题】:Replacement System Classloader for Classes In Jars containing Jars包含罐子的罐子中的类的替换系统类加载器
【发布时间】:2011-07-19 19:30:10
【问题描述】:

到目前为止,我看到的自定义 ClassLoader 的示例涉及对 URLClassLoader 进行子类化,并使用该特定实例来加载资源中的类。

我曾尝试寻找替代方法来替换 SystemClassLoader,这样我的 ClassLoader 就可以用于不在类路径中的类。

我试过Thread.currentThread().setContextClassLoader,但它似乎不起作用。

有可能吗?

【问题讨论】:

  • 当您说“以便可以为不在类路径中的类咨询我的 ClassLoader”时,您是指像 java.lang.* 这样的普通系统类还是要加载额外的第 3 方类?
  • 第三方类...

标签: java jar classloader


【解决方案1】:

虽然这是一个老问题,但确实有办法替换系统ClassLoader。 然而,通过反思,你可能会得到比你讨价还价的更多。

        Field scl = ClassLoader.class.getDeclaredField("scl"); // Get system class loader
        scl.setAccessible(true); // Set accessible
        scl.set(null, new YourClassLoader()); // Update it to your class loader

这应该适用于 Oracle JVM。

【讨论】:

  • 这当然是一个 hack,它依赖于一个可以在 java 版本之间更改的私有变量,但它让我能够解决一个 jar 和调用 System.System 的第 3 方依赖项中的代码的问题。 getClassLoader() 加载一个类。将 one-jar 的类加载器推到最上面就可以了。
  • @Xyene 在我完成工作后 - 如果我将类加载器放回 URLClassLoader.getSystemClassLoader() 应用程序行为会好吗?
  • @ha9u63ar 我想这取决于您的用例;如果您不小心,您的类很可能会出现可见性问题(例如,从系统类加载器加载的 A 类将无法从您的类中看到 B 类)。我已经有几年没有做过类似的事情了,但把系统加载器放回去可能没有什么好处。
  • @Xyene 以这种方式使用时,我的一个类出现链接错误。我想这个解决方案不适合 web 应用程序,因为 Servlet 容器将拥有它自己的类加载器,如果我无法重新建立委托链,我就有麻烦了。
【解决方案2】:

使用java.system.class.loader 属性运行 JVM:

java -Djava.system.class.loader=myClassLoader myApplication

【讨论】:

  • 我正在寻找一种排除修改 JVM 命令行的解决方案
  • 如果要更换系统类加载器,没有这个办法。您可以在代码中创建您的专有类加载器并使用它来加载类,但它不会是系统类加载器。对于大多数情况,通常创建专有的类加载器就足够了。
  • stackoverflow.com/questions/68380968/… - 对这个问题有任何想法吗?
猜你喜欢
  • 2015-06-27
  • 2016-01-04
  • 2012-09-03
  • 1970-01-01
  • 2012-06-04
  • 1970-01-01
  • 2018-04-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多