2024状态 Clojure调查中分享您的观点!

欢迎!请查阅关于页面以获取更多有关此工作方式的信息。

0
编译器

编译一个引用未加载(或未初始化)类的函数会触发其静态init。当初始化静态加载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

评论者:alexmiller

Rich已批准对该问题进行1.7版筛选,但我认为在没有更好地理解之前,我无法将其标记为已筛选。这里的描述、代码和原因信息不足以让我了解问题的实质或为什么该修复是正确的。修复似乎解决了症状,但我担心这只是症状,而更深入地了解实际原因可能需要不同的或更好的修复。

补丁的演变由CLJ-1544(一个因其他原因被撤回的补丁)中的错误驱动。从头开始,那些修改是否必要和正确?

为什么这个变量的集合需要将纯净的实现推进绑定中?为什么不使用其他变量(比如在 load() 中推进的变量)?这里选择的集合似乎与 ReifyParser 中的集合相匹配 - 为什么?为什么只有当它们被绑定时才推进(也就是说,为什么“未绑定”不是“已绑定但为空”)?我们是否影响到了性能?

完全弹出,CCW 实际上能否完成这件事?描述中说“编译一个引用了未加载(或未初始化)类的函数会触发其 init 静态方法” - 这种加载甚至会发生吗?我们能获得一个真正演示 CCW 最初做什么的示例吗?

0

评论者:laurentpetit

Alex,如果你在给定的示例中回答,我认为可以回答“CCW 做的这件事是否可做”的问题。

关于“类初始化是否应该在它可以简单地加载时发生”的问题是一个好问题。关于这个问题的报告已经在 Clojure 列表中提出,我猜至少有一个关于在 Clojure 中把更多的 classForName 替换为 classForNameNonLoading 的 CLJ 问题。
例如,它阻止了在代码做一些对运行时假设后引用具有代码的静态初始化器的 Java 类。这是 Eclipse / SWT 的问题,我记得 Colin 提到过类似的问题。而且,这很可能是每次尝试将 clojure 代码与具有在编译时由静态初始化器触发(这是传递性的)的假设它们在正确目标运行时环境中初始化的 Java 类进行交互时出现的问题。

我不知道是否预先阻止初始化类静态方法在它们被引用(通过互操作调用 - 构造函数、字段、方法、静态字段、静态方法)将足以消除这个问题和补丁试图解决的问题的范围。我不声称完全了解正在发生的事情(基督ophe 和尼古拉对分析问题和创建补丁有很大帮助),但根据我的理解,这就像是一部“盗梦空间”电影中的 bug。编译一个 fn 会触发编译另一个 fn(这里是通过通过 java 初始化器加载 clojure 命名空间)。

如果当它们通过互操作调用(构造函数、字段、方法、静态字段、静态方法)引用时按下类静态方法来避免初始化是唯一可能引起这种“编译中的编译”场景的因素,那么是的,保护编译过程(正如尼古拉尝试做的那样)可能不是必要的,而只修复不期望的加载可能是足够的。

0
参考:https://clojure.atlassian.net/browse/CLJ-1620(由 cgrand 报告)
...