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发表

实际上,用(: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发表

我必须考虑一个方式来复制该错误,它不是一个简单的场景。
它涉及到从eval上下文编译一个命名空间。

0

评论者:laurentpetit

你好,还有机会让这个问题在1.7版中得到解决吗?

0

评论者:alexmiller

本计划之外的事 - 对您有什么影响吗?

0

评论者:laurentpetit

影响是,我需要为CCW使用Clojure的补丁版本。
虽然目前跟踪clojure的主分支并不难,并定期rebasing或者应用补丁,但这仍然是一种浪费时间的行为。

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-initalizer-v4.patch

0

评论者:alexmiller

这些补丁在引入的变化方面是等价的;它们只是在diff上下文的大小上有所不同。

...