请在 2024 年 Clojure 状况调查中分享您的想法!

欢迎!请在 关于 页面查看更多关于此功能的信息。

0
java.classpath

我有一个项目将数据存储在它期望在类路径中找到的资源中。当项目使用 java.classpath 0.2.2 和 clojure-maven-plugin 1.3.20+,调用 (java.classpath/classpath) 时会显示意外的结果 - 它显示了一些 Sun 的东西,但没有依赖项,没有 Clojure,也没有我的代码或资源。Clojure 似乎功能正常,只是调用 classpath api 时的有些问题。

比较一下

java.classpath 0.1.0 和 c-m-plugin 1.3.9 表现如预期。

java.classpath 0.1.0 和 c-m-plugin 1.3.20 可能会存在问题,有时只显示类路径上的一个似乎为空清单的项目。

在此处跨帖到 clojure-maven-plugin
https://github.com/talios/clojure-maven-plugin/issues/81

8 答案

0

评论者:drlivingston

也与这个 Java 版本有关
Java 版本:1.7.0_45,厂商:Oracle Corporation

0

评论者:stuart.sierra

我可以确认 java.classpath 的所有版本都与 clojure-maven-plugin 1.3.13 及之后的所有版本有此行为。

从 clojure-maven-plugin 的 1.3.13 版本开始,该插件不再使用 {{-cp}} 在命令行上指定 Java 类路径,而是生成一个包含真实类路径的清单文件的临时 JAR 文件,并使用 {{-jar}} 启动 Java。

请参阅clojure-maven-plugin(链接:[见 pull request #58](https://github.com/talios/clojure-maven-plugin/pull/58) text: pull request #58),其中包含(链接:[见 commit 8d8e90e4](https://github.com/talios/clojure-maven-plugin/commit/8d8e90e41806a6927c11347e6fc13344ba53c887) text: commit 8d8e90e4)。

{{clojure.java.classpath/classpath}} 用于查看加载 Clojure 的 classloader,在这种情况下是 {{sun.misc.Launcher$AppClassLoader}} 的子 classloader。AppClassLoader 是 (链接:[见 URLClassLoader](http://docs.oracle.com/javase/6/docs/api/java/net/URLClassLoader.html) text: URLClassLoader) 的子类,但其 (链接:[见 getURLs()](http://docs.oracle.com/javase/6/docs/api/java/net/URLClassLoader.html#getURLs()) text: getURLs()) 方法仅返回 JAR 文件的 URL。没有明显的 API 可以在不打开和读取 JAR 文件内容的情况下获取manifest文件的 {{Class-Path}} 属性。

0
by

评论者:stuart.sierra

进一步深入研究 OpenJDK 源代码后,发现 URLClassLoader 会延时读取 JAR manifest 文件,以需为主,以加载类或资源。要找到 URLClassLoader 可能打开的 所有 URL 列表,你必须重新实现此逻辑以读取所有 manifest 文件。它还必须是递归的(JAR manifest 指向另一个包含 manifest 的 JAR 文件)并检测循环。

0
by

评论者:drlivingston

感谢您进行调查。
我是否理解这是 clojure-maven-plungin 和 clojure.java.classpath 应该一起进行的正确/预期行为?

所以我当时进入 jar 文件(虽然我意识到我认为我没有检查嵌套的 jar 文件 - classloader 是否检查嵌套文件?),你现在说还有一个第三个案例我需要覆盖,对吗?: manifest 文件?在 clojure.java.classpath 中有读取它们的实用方法吗?

我正在使用类似的代码来识别类路径上的所有可访问内容

https://github.com/drlivingston/kr/blob/master/kr-core/src/main/clojure/edu/ucdenver/ccp/utils.clj#L101

谢谢,
凯文

0
by

评论者:stuart.sierra

目前,clojure.java.classpath 无法处理 JAR Manifest 文件和嵌套 JAR 文件。正如我在之前的评论中所描述的,实现对此的支持将很困难,并且在我接下来的时间里很可能不会成为我的优先事项。我愿意审查添加此功能的补丁,但它必须证明它能够保护免受递归循环的影响。

通过我对《JAR 文件规范》(链接:http://docs.oracle.com/javase/7/docs/technotes/guides/jar/jar.html 文本)的阅读,clojure-maven-plugin 的行为可能与 JAR 规范的精神相违背,该规范将 “Class-Path” 清单属性描述如下:

{quote}
"Class-Path: 此属性的值指定了应用程序或扩展程序需要的扩展或库的相对 URL。"(增加了强调)
{quote}

clojure-maven-plugin 正在创建一个包含指向其他 JAR 文件的“Class-Path”属性,而这些 JAR 文件不是嵌入在包含清单的 JAR 文件中的绝对 URL。

我总是认为带有 Class-Path 属性的 JAR 清单文件仅在打包完整应用程序或 JDK 扩展时使用,而不仅仅是作为一种在开发期间指定类路径的机制。显然,这是可能的,正如当前的 clojure-maven-plugin 所演示的那样,但这不是我希望依赖的特性。

一般来说,JDK 不支持列举类路径上的所有文件,因为类路径可以包括指向远程资源的 URL,这些资源需要时才会下载。

0
通过

评论者:drlivingston

有趣。我没有意识到其中的一些内容如此灵活。
感谢您的评论。

所以递归地迭代 CP 可能是一件坏事,尽管我认为这并不比询问最后,最深角的 CP 中的某物要糟,对吧?

我一直在将资源文件放在 CP 中,然后让应用程序通过文件名称的前缀来查找它们。例如,查找所有 "foo.bar" 并得到 "foo.bar.baz1" 和 "foo.bar.baz2" 等,而不需要应用程序知道那里有什么或者需要生成或维护清单。这是处理类路径上资源的已知反模式吗?

0
通过

评论者:stuart.sierra

{quote}
这是处理类路径上资源的已知反模式吗?
{quote}

是的。

0
通过
参考: https://clojure.atlassian.net/browse/CLASSPATH-6(由 alex+import 报告)
...