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

欢迎!请参阅关于页面了解有关如何使用此功能的一些更多信息。

0
编译器

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

它防止了在某些环境中(Rational)CCW 的工作,因为生成的函数的静态初始化超过 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编译执行的做法完全没有头绪,但已找出问题所在。
更新后的补丁仅在已绑定时(在eval中)绑定合适的变量。

0

评论者:alexmiller

现在使用转瞬即逝的绑定映射是否值得?

0

评论由:bronsa 提出

这是一种合理的想法,已将补丁更新为使用一个转瞬即逝的映射。

0

评论者:michaelblume

我们可以增加一个测试来验证v2补丁的存在吗?最好是与CLJ-1544补丁独立?我可以尝试自己编写一个,但我不太熟悉Clojure编译器的内部结构。

0

评论由:bronsa 提出

我将思考如何重现该错误,这是一个不是那么简单的复制场景。
它涉及到从一个已评估的上下文中编译一个命名空间。

0

评论者:laurentpetit

你好,还有机会修复此问题到1.7版本吗?

0

评论者:alexmiller

我本来没有这个打算——对你有什么影响吗?

0
回复者

评论者:laurentpetit

影响在于我需要使用CCW的修复版本Clojure。
虽然目前跟踪Clojure的主要分支并定期重新基准化或重新应用补丁并不难,但仍是一种浪费。

0
回复者

评论者:alexmiller

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

0
回复者

评论者:alexmiller

与v4补丁相同,但提供了更多的差异上下文。

0
回复者

评论者:laurentpetit

按个人观点,补丁字段中提到的文件不是正确的文件。

0
回复者

评论者:alexmiller

是哪一个呢?

0
回复者

评论者:laurentpetit

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

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

0
回复者

评论者:alexmiller

这些补丁就引入的变化而言是等效的;它们只是差异上下文不同。

...