2024年Clojure现状调查!中分享您的看法。

欢迎!请参阅关于页面获取更多关于这个工作的信息。

0
编译器

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

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

重现步骤

加载leak.main命名空间并运行注释中的代码:第一个函数尽管与第二个函数完全相同,但有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

同样Ghadi是对的,事实上用(:foo {})替换thunk-fail.core的全部主体就足够了。

看起来问题是出在AOT(预编译)顶层关键字查找点的编译上,我猜测这个补丁可能是因为某种原因阻止了__init静态初始化器的正确生成。

0

评论人:bronsa

我对lein compile的执行过程完全一头雾水,但已经找到了问题所在。
更新的补丁仅在已绑定的变量时(在eval中)绑定相应的变量。

0

评论者:alexmiller

现在在绑定映射中使用临时存储(transients)是否有意义?

0

评论人:bronsa

有道理,补丁已更新,使用临时映射

0

评论者:michaelblume

我们能否添加一个测试,使得v2补丁存在时测试失败?最好是独立的CLJ-1544补丁。我可以尝试自己编写一个,但我不太熟悉Clojure编译器内部结构。

0

评论人:bronsa

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

0

评论者:laurentpetit

你好,这个问题的修复是否有机会进入1.7版本?

0

评论者:alexmiller

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

0
by

评论者:laurentpetit

影响是,我需要为CCW使用Clojure修补版本。
虽然目前跟踪cljure的主分支并在其上定期rebase或reapply patch并不困难,但这仍然是一种时间浪费。

0
by

评论者:alexmiller

在我们达到RC之前,我将与Rich商量是否可以在1.7版本中筛选。

0
by

评论者:alexmiller

与v4补丁相同,但只是具有更多的diff上下文。

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
by

评论者:alexmiller

这些补丁在引入的更改方面是等效的;它们只是diff上下文的不同。

...