请分享您的想法,参加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: File name too long}}异常。

这个问题很难找到,可能是因为它没有提到,或者标记了core.match,尽管这是更常见的故障原因之一。

有什么进展吗?该票据被标记为“关键”。
我为它添加了标签。它不在我们1.12的列表上,但我已经在我们的列表中,将在1.13中查看。

10 答案

0 票数

评论者:martinraison

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

0 票数

评论者:panewman

我在 Windows 下尝试使用 clojure.core.match 和 13 个模式,编译失败。我假设这是问题的根源。

0 票数

评论者:chrisbetz

关于这一点还有一些信息

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

Clojure 并非唯一的这个问题,Scala 也受到了严重的打击:https://issues.scala-lang.org/browse/SI-3623

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

对于所有受到这个问题的困扰的人,一个可能的工作around方案可能是 Mario Pastorelli 在注释 https://issues.scala-lang.org/secure/ViewProfile.jspa?name=melrief) 中提出的 (https://issues.scala-lang.org/browse/SI-3623?focusedCommentId=76104&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-76104)

使用未加密的文件系统临时存储类文件,也许可以通过一个 tempFS 在内存中保存内容。这不是最好的方法,因为我们不喜欢留下重要的东西未加密...

0 票数

评论者:alexvong1995

你好,

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

我认为解决方法之一是提供一个选项,将类文件作为具有较短的文件名的 jar 包装起来,这样类名可以保持不变(压缩文件的名称可以无限长,对吧?).你怎么看?

顺便说一下,我正在使用 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 报告)
...