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

欢迎!有关如何工作的更多信息,请参阅关于页面。

0
编译器

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

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

复现步骤

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

实际上,Ghadi是正确的,实际上,用(:foo {})替换thunk-fail.core的主体就足够了。

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

0

评论者:bronsa

我仍然完全没有头绪,关于lein compile做了什么,但我想出了问题。
更新的补丁只在实际绑定的情况下(在eval中)绑定适当的var。

0

评论区:由 alexmiller 发表

现在在 bindings map 上使用 transient 是否值得考虑?

0

评论者:bronsa

有道理,更新了补丁,使用 transient map

0

评论区:由 michaelblume 发表

我们是否可以添加一个用于测试的测试用例?以便在存在 v2 补丁的情况下会失败,最好与 CLJ-1544 补丁独立?我可以尝试自己编写一个,但我不太熟悉 Clojure 编译器的内部结构。

0

评论者:bronsa

我需要思考如何重现该问题,这是一个不容易重现的场景。
它涉及到从一个已评估的上下文中编译一个命名空间。

0

评论区:由 laurentpetit 发表

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

0

评论区:由 alexmiller 发表

我没有计划这么做 - 对您的冲击有多大?

0

评论区:由 laurentpetit 发表

影响是我需要使用 CCW 的修补版 Clojure。
虽然目前跟踪Clojure的主分支并定期在其基础上归并或重新应用补丁还不是特别难,但这仍然是一种时间浪费。

0
by

评论区:由 alexmiller 发表

在我们达到候选发布版本之前,我将和Rich确认是否可以在1.7版本之前进行筛选。

0
by

评论区:由 alexmiller 发表

与v4补丁相同,只是有更多的差异上下文

0
by

评论区:由 laurentpetit 发表

在补丁字段中提到的文件按我之见不是正确的那个

0
by

评论区:由 alexmiller 发表

哪一个才是?

0
by

评论区:由 laurentpetit 发表

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

补丁:0001-CLJ-1620-避免在静态初始化器中造成常量泄漏-v4.patch

0
by

评论区:由 alexmiller 发表

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

...