2024 Clojure状态调查!中分享您的想法。

欢迎!请参阅关于页面以了解其工作方式的相关更多信息。

0
编译器

编译引用未加载(或未初始化)类的函数会触发其初始化静态。当初始化静态加载Clojure代码时,一些常量(我认为是源代码)会泄漏到正在编译的函数的常量池中。

由于结果的函数的静态初始化超过64K,这阻止了CCW在某些环境(Rational)中工作。

重现步骤

加载leak.main ns并运行注释中的代码:第一个函数尽管与第二个相同,但有15个额外的字段。

`
(ns leak.main)

(defn first-to-load [])
leak.Klass/foo)

(defn second-to-load [])
leak.Klass/foo)

(comment
=> (map (comp count #(.getFields %) class) [first-to-load second-to-load])
(16 1)
)
`

`
package leak;

import clojure.lang.IFn;
import clojure.lang.RT;
import clojure.lang.Symbol;

public class Klass {
static {

RT.var("clojure.core", "require").invoke(Symbol.intern("leak.leaky"));

}
public static IFn foo = RT.var("leak.leaky", "foo");
}
`

`
(ns leak.leaky)

(defn foo
"Some doc"
[]
"hello")

(def unrelated 42)
`

https://gist.github.com/cgrand/5dcb6fe5b269aecc6a5b#file-main-clj-L10

补丁: clj-1620-v5.patch

33 答案

0

评论者:bronsa

实际上,用(:foo {})替换thunk-fail.core的全部体就足够了。

这个问题似乎与AOT(重新)编译顶层关键字查找站点有关,我猜测,由于某种原因,这个补丁阻止了生成正确的__init静态初始化器。

0

评论者:bronsa

我对lein compile正在执行的操作毫无头绪,但我已找出问题所在。
更新的补丁只在变量已经绑定的情况下,在eval中将相应的变量绑定。

0

评论者:alexmiller

现在使用transients在绑定映射中对吗?

0

评论者:bronsa

有道理,已更新补丁以使用transient映射

0

评论者:michaelblume

我们可以添加一个测试来证明v2补丁下的失败?最好是与CLJ-1544补丁无关的独立测试?我可以尝试自己编写一个,但是我并不熟悉Clojure编译器的内部结构。

0

评论者:bronsa

我必须考虑如何重现此错误,这并非一个简单的场景。
它涉及到从一个已评估的上下文中编译命名空间。

0

评论者:laurentpetit

你好,是否有机会让这个问题得到1.7的支持?

0
by

评论者:alexmiller

我没有计划这么做,这对你有什么影响吗?

0
by

评论者:laurentpetit

影响是,我需要为 CCW 使用已修复版本的 Clojure。
目前虽然跟踪 clojure 的主分支并定期重新合并或重新应用补丁并不难,但仍然是浪费时间。

0
by

评论者:alexmiller

在我们进入 RC 之前,我会跟 Rich 看看是否可以在 1.7 中修复。

0
by

评论者:alexmiller

与 v4 补丁相同,但具有更详细的不同上下文

0
by

评论者:laurentpetit

在我看来,补丁字段中提到的文件不是正确的文件。

0
by

评论者:alexmiller

哪个是?

0
by

评论者:laurentpetit

我认为您之前的评论与 clj-1620-v5.patch 有关,但在描述的末尾有以下一行

补丁:0001-CLJ-1620-avoid-constants-leak-in-static-initalizer-v4.patch

0

评论者:alexmiller

这些补丁在引入的更改方面是等价的;它们只是在diff上下文上有差异。

...