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

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

0
编译器

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

这阻止了 CCW 在某些环境中(Rational)正常工作,因为最终函数的静态初始化超过了 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

评论者:alexmiller

Rich 已经批准了 1.7 版本对此进行检查,但我感觉除非我更好地了解这个问题,否则无法将其标记为已检查。这里的描述、代码和原因信息不足以使我理解问题的实际情况或为什么修复方法是正确的。该方法似乎解决了症状,但我担心这只是症状,而更好地理解实际原因可能会带来不同的或更好的修复方法。

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

为什么这组变量需要将干净的实现推送到绑定中?为什么不是其他一些变量(比如在 load() 中推入的变量)?这里选择的集合似乎与 ReifyParser 的集合相匹配,为什么?为什么只有在变量绑定时才需要推送(也就是说,“未绑定”是否与“已绑定但为空”相同)?我们是影响了性能吗?

CCW 是否甚至能真正做到完全弹出,描述中说“编译引用非加载(或未初始化)类的函数触发其静态初始化”- 这种加载是否应该发生?我们可以提供一个实际演示 CCW 最初行为示例吗?

0

评论者:laurentpetit

Alex,如果您在给定示例中回答这个问题,我认为就可以回答关于“CCW 应该能做什么”的问题。

关于“当类初始化可以只是加载时是否应该发生初始化”的问题是一个很好的问题。在 Clojure 列表上已经出现过关于此问题的几份报告,我觉得至少有一个 CLJ 更改问题建议在 Clojure 中将“classForName”更改“classForNameNonLoading”的实例进行更改。
例如,这防止了在运行时进程中做一些假设的 java 类代码引发静态初始化。这是 Eclipse / SWT 的问题,我记得 Colin 提到过类似的问题,Cursive 也会出现这个问题。并且可能每次尝试对与具有静态初始化器的 java 类交互的 clojure 代码进行 AOT 编译时都会出现这个问题(这是传递性的),假设它们是在适当的目标运行环境中被初始化的。

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

如果防止在引用(通过互操作调用 - 构造函数、字段、方法、静态字段、静态方法)时初始化类静态方法,这是导致“编译时的编译”场景的最后一个潜在问题,那么是的,像 Nicolas 尝试保护编译过程可能不是必需的,只需修复不希望的加载就足够了。

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