2024年Clojure调查中分享您的想法!

欢迎!请参阅关于页面以了解更多关于如何使用此系统信息。

+6
编译器
编辑

Clojure编译器生成的类名可以任意长,超过文件系统允许的最大文件名长度。例如,当您函数嵌套程度太深时会发生这种情况

(defmacro nestfn [n & body]
  (if (> n 0)
    `(fn [] (nestfn ~(- n 1) ~@body))
    body))

(def myf (nestfn 100 "body"))

编译此内容将抛出{{java.io.IOException: 文件名太长}}异常。

这个问题很难找到,可能是因为它没有提到,也没有打上core.match标签,尽管这是更常见的诱因之一。

有没有什么进展?该票据被标记为“关键”。
我已为其添加了标签。它不在我们的1.12列表中,但我将其列入我们的1.13审核列表。

10 个答案

0
by

评论由:martinraison 提出

Scala 社区在一段时间前发现了这个问题,现在编译器有一个 {{max-classfile-name}} 参数(默认为 255)。当超过限制时使用哈希。或许我们应该考虑一些类似的东西?

0
by

评论由:panewman 提出

我尝试使用 clojure.core.match 和 13 种模式失败,似乎这是问题的根本原因。

0
by

_评论由:chris<em>betz</em> 提出

关于这个问题的更多信息

我的同事遇到了这个问题,因为他使用 Linux / eCryptfs(与通常使用的 FileVault 加密的 macOS 相比,这里的限制 143 比较小):参见 https://bugs.launchpad.net/ecryptfs/ bug/344878

然而,Clojure 并非唯一遇到这个问题,Scala 也受到严重打击:<a rel="nofollow" href="https://issues.scala-lang.org/browse/SI-3623" target="_blank">https://issues.scala-lang.org/browse/SI-3623

这个问题没有“简单”的解决方案,显然,截断文件名(如 Scala 所做的那样)会带来很多其他问题。

对于所有被这个问题困扰的用户,一个可能的解决方案可能是 Mario Pastorelli 在评论 <a rel="nofollow" href="https://issues.scala-lang.org/secure/ViewProfile.jspa?name=melrief" target="_blank">https://issues.scala-lang.org/secure/ViewProfile.jspa?name=melriefhttps://issues.scala-lang.org/browse/SI-3623?focusedCommentId=76104&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-76104

使用非加密的文件系统临时存储类文件,例如通过有 temFS 保留内存中的内容。这不是最好的方法,因为我们不喜欢留下重要内容不加密...

0
by

评论由:alexvong1995 提出

你好,

当使用 clojure.core.match 时,我遇到了相同的问题。我展开函数定义,并观察到宏展开的定义是深度嵌套的。

我认为解决它的一个方法是为将类文件包装成 jar 文件并提供一些较短的文件名,这样类名就可以保持不变(zip 文件名可以任意长,对吧?)。你有什么看法?

顺便说一句,我正在使用clojure 1.9.0,因此我认为我们应该说这个漏洞也影响到1.9版本。

0

评论由:alexvong1995 提出

我想出了一个概念验证补丁。当类名长度超过255时,编译器现在输出jar而不是类。jar名称只是类名的一个(左)截断。

假设 **compile-path* 设置为 "build",那么你需要将 build/ 添加到你的类路径中,以便可以找到jar文件。

这个补丁只是一个概念验证,理想情况下,所有长命名的类都应该放入一个大的jar中,以避免解压缩许多文件。此外,用户应该能够指定 **compile-name-max** 和 **compile-jar-name**。最后,代码相当丑陋,我应该把它分成几个函数。

0

做出的评论:alexmiller

Alex - 我们不会输出jar文件。这与Clojure运行时许多方面相矛盾。

0

做出的评论:[email protected]

如果这个评论离题了,我很抱歉。原始示例让我有些困惑,也许它应该是

`
(defmacro nestfn [n & body]
(if (> n 0)

`(fn [] (nestfn ~(dec n) ~@body))
`(do ~@body)))

`

这样,{{(trampoline (nestfn 10 "foo"))}} 会返回 "foo"。然而,我在 macOS 上用 n=1000 时得到一个 CompilerException java.lang.StackOverflowError。

0

做出的评论:gsnewmark

@Alex Miller 你好!将像Scala那样的方法(如果名称太长,则对名称进行哈希处理)程度的补丁会被考虑吗?因为这个方法会打破二进制兼容性,因此肯定会被默认禁用,但可以通过使用新的编译器选项来启用名称哈希。这种方法肯定有助于我们特定的情况,但我不确定它是否足够通用以包含在编译器中,所以我还没有开始工作。

0
_做出的评论:alexmiller_

不会做出任何破坏性的更改。计划是在当前策略不起作用时切换到第二种策略。
0
参考: https://clojure.atlassian.net/browse/CLJ-1852(由 alex+import 提出)
...