请在2024 Clojure状态调查中分享您的看法!

欢迎!有关本网站如何运作的更多信息,请参阅关于页面。

+3
java.classpath

"我的应用程序的类路径是什么?"

事实上,这个问题并没有一个简单直接的答案。

运行Java的方式有很多,每种方式都可能导致应用程序类路径的不同定义。历史上,clojure.java.classpath库使用了多种启发式方法来寻找和返回Java类路径。

当前的方法是Java 9的一个折衷方案,因为在Java 9中,默认类加载器不是URLClassLoader的实例。现在,这给CIDER用户带来了问题,当cider-jack-in注入JDK源路径(见下文)时。

我一直在查看clojure.java.classpath的历史,特别是

似乎没有一个单一的解决方案可以在所有情况下都给出正确的结果。

  • 使用系统属性java.class.path在应用程序容器环境中会产生错误结果(CLASSPATH-1)。
  • 在Java 9+中,从URLClassLoaders获取类路径行不通(CLASSPATH-8)。
  • 合并结果将为像CIDER和tools.namespace这样的工具提供更全面的覆盖,但可能会为容器中的应用程序返回错误结果。

我不确定如何进行。我很担心再次做出改变来解决最新问题,从而破坏更早的使用。

有关讨论,请参阅

1 答案

+1
by
编辑 by

对此稍作补充,列举classpath并不直接的原因是Java从未定义过一种支持的方式来做这件事。

系统类加载器,它通常加载在java.class.path系统属性中找到的依赖,只能确保其类型为ClassLoader,这不是可枚举的。

  • 在Java 9之前,人们可以通过依赖实现细节来枚举系统类加载器:这通常会返回一个URLClassLoader,该类具有getURLs方法。然而,这是一个没有文档说明的行为。

  • 从Java 9开始,系统类加载器的实现被更改为一个不可枚举的内部类。

  • 直接使用java.class.path系统属性是基于某些运行时行为,而不是检查实际行为的输出。这种假设在许多情况下都成立,但在其他情况下则失败。

理想的解决方案是,在Java 9+上能够枚举系统(和平台)类加载器加载的资源的一种方式,以便整个classpath层次都可以枚举。

如果没有这样的方案,在Java 9+上依赖java.class.path属性可能是必要的。如果是这样做的话,下一个最好的方案应至少适应以下两种特殊情况:

  1. 应用程序可能在一个容器中运行。
  2. 动态类加载器可能会在运行时添加资源。
by
我看到这个,它声称是一个通用的classpath枚举器。还没试用过 https://github.com/classgraph/classgraph
by
我已经看到了,但也没有时间深入研究。似乎可检索的信息的大部分都可以追溯到那个库的作者。他对Jigsaw支持的笔记有一定的帮助:[链接](https://github.com/classgraph/classgraph/issues/36)。不过,他的灵感时刻似乎并没有帮我们解决问题。

我尝试快速使用模块系统,但并不是一帆风顺。以下是一些笔记:

- 在Java 9+模块系统中,类路径上的所有类都属于未命名的模块,每个类加载器都有自己的未命名的模块。
- 可以从ModuleReference对象中枚举模块的资源。
- 很遗憾,未命名的模块并不是真正的模块;它们不在模块层或配置中。
- 因此,似乎没有从未命名的模块的Module对象中获取ModuleReference的方法。
...