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

欢迎!有关本网站的更多信息,请参阅关于页面。

0
编译器

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

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

重现步骤

加载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

事实上,替换thunk-fail.core的整个主体为(:foo {})就足够了。

这似乎问题出在AOT(再次)编译顶级关键字查找位置上,我的猜测是,由于某种原因,这个补丁阻止了__init静态初始化器的正确生成。

0

评论者:bronsa

我仍然不知道lein compile在做些什么,但我已经找到了问题。
更新后的补丁仅当已经绑定时才在评估中绑定适当的变量。

0

评论者:alexmiller

现在在绑定映射上使用transients是否有意义?

0

评论者:bronsa

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

0

评论者:michaelblume

我们是否可以添加一个测试,该测试在出现v2补丁的情况下会失败?最好与CLJ-1544补丁独立?我可以尝试自己编写一个,但是我对Clojure编译器内部机制不是很熟悉。

0

评论者:bronsa

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

0

评论者:laurentpetit

还有没有可能让这个问题进入1.7版本?

0

评论者:alexmiller

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

0

评论者:laurentpetit

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

0

评论者:alexmiller

在我们进入RC之前,我将与Rich确认是否可以在1.7版本中筛选。

0

评论者:alexmiller

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

0

评论者:laurentpetit

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

0

评论者:alexmiller

哪一个呢?

0

评论者:laurentpetit

我认为您的先前的评论与clj-1620-v5.patch相关,但在描述的最后有以下行

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

0

评论者:alexmiller

这些补丁在引入的变化上等效;它们只是具有不同的diff上下文。

...