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

欢迎!请参阅关于页面以了解更多相关信息。

0
编译器

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

这阻止了在某些环境中(Rational)CCW 的工作,因为最终函数的静态初始化超过了 64K。

重现步骤

加载 leak.main Namesp 并运行注释中的代码:第一个函数具有 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
"一些文档"
[]
"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执行的操作甚至是一件应该可以做的事情吗?描述说“编译一个引用未加载(或未初始化)类的函数会触发它的初始化静态方法” —— 这种加载真的会发生吗?我们能提供一个示例来实际演示CCW最初所做的事情吗?

0

评论者:laurentpetit

Alex,如果你想解答关于“CCW所做的事情是否应该可以做”的问题,我建议你在给出的示例中回答这个问题。

“当类可以只被加载时,类的初始化是否应该发生”是一个很好的问题。在 Clojure 列表中已经有多份关于这个问题的报告,我猜至少有一个 CLJ 关于在这里和那里改变 classForName 为 classForNameNonLoading 的问题。
例如,它会防止在代码进行关于它在其中初始化的运行时假设时,引用有代码的静态初始化器的 java 类。这是 Eclipse / SWT 的一个问题,我记得Colin提到过类似的问题。这可能是每次尝试AOT编译与具有静态初始化器(由编译触发)的 java 类相互操作的 clojure 代码时出现的问题(这是递归的),并且它们对在正确的目标运行时环境中初始化的假设。

我不知道防止最初就发生类静态方法的初始化是否足以消除这个bug和提出的补丁试图解决的问题。我不完全清楚发生了什么(Christophe和Nicolas在分析问题和创建补丁方面提供了极大的帮助),但我理解它是一种“像电影《盗梦空间》一样的”bug。编译一个fn,它触发编译另一个fn(在这里是通过通过 java 初始化器加载 clojure 命名空间)。

如果防止当它们被引用时(通过 interop 调用 - 构造函数、字段、方法、静态字段、静态方法等)初始化类静态方法是目前唯一可能引发此类“编译中的编译”场景的因素,那么是的,就像Nicolas试图做的保护编译过程可能不是必需的,仅仅是修复不希望的加载可能就足够了。

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