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

欢迎!请参阅关于页面以了解更多有关此功能的信息。

0
Clojure

此错误的最明显症状是在类路径中有一个名为'w'的类(默认包)的情况下尝试加载Clojure的核心类。例如

java -cp hotspotapi.jar:clojure-1.4.0-slim.jar clojure.main

(其中hotspotapi.jar是一个典型的混淆JAR文件)会导致

thread "main"中的异常: java.lang.ExceptionInInitializerError

at clojure.main.<clinit>(main.java:20)

原因: java.lang.NoSuchFieldException: close, compiling:(clojure/core.clj:6139)

at clojure.lang.Compiler.analyzeSeq(Compiler.java:6462)
at clojure.lang.Compiler.analyze(Compiler.java:6262)
at clojure.lang.Compiler.analyze(Compiler.java:6223)
at clojure.lang.Compiler$BodyExpr$Parser.parse(Compiler.java:5618)
at clojure.lang.Compiler$TryExpr$Parser.parse(Compiler.java:2178)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:6455)
at clojure.lang.Compiler.analyze(Compiler.java:6262)
at clojure.lang.Compiler.analyze(Compiler.java:6223)
at clojure.lang.Compiler$BodyExpr$Parser.parse(Compiler.java:5618)
at clojure.lang.Compiler$LetExpr$Parser.parse(Compiler.java:5919)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:6455)
at clojure.lang.Compiler.analyze(Compiler.java:6262)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:6443)
at clojure.lang.Compiler.analyze(Compiler.java:6262)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:6443)
at clojure.lang.Compiler.analyze(Compiler.java:6262)
at clojure.lang.Compiler.analyze(Compiler.java:6223)
at clojure.lang.Compiler$BodyExpr$Parser.parse(Compiler.java:5618)
at clojure.lang.Compiler$FnMethod.parse(Compiler.java:5054)
at clojure.lang.Compiler$FnExpr.parse(Compiler.java:3674)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:6453)
at clojure.lang.Compiler.analyze(Compiler.java:6262)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:6443)
at clojure.lang.Compiler.analyze(Compiler.java:6262)
at clojure.lang.Compiler.access$100(Compiler.java:37)
at clojure.lang.Compiler$DefExpr$Parser.parse(Compiler.java:518)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:6455)
at clojure.lang.Compiler.analyze(Compiler.java:6262)
at clojure.lang.Compiler.analyze(Compiler.java:6223)
at clojure.lang.Compiler.eval(Compiler.java:6515)
at clojure.lang.Compiler.load(Compiler.java:6952)
at clojure.lang.RT.loadResourceScript(RT.java:359)
at clojure.lang.RT.loadResourceScript(RT.java:350)
at clojure.lang.RT.load(RT.java:429)
at clojure.lang.RT.load(RT.java:400)
at clojure.lang.RT.doInit(RT.java:436)
at clojure.lang.RT.<clinit>(RT.java:318)
... 1 more

原因: java.lang.NoSuchFieldException: close

at java.lang.Class.getField(Class.java:1537)
at clojure.lang.Compiler$StaticFieldExpr.<init>(Compiler.java:1180)
at clojure.lang.Compiler$HostExpr$Parser.parse(Compiler.java:923)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:6455)
... 37 more

找不到主类: clojure.main。程序将退出。

为了理解发生了什么,请考虑以下简单的测试

import java.io.StringReader;

import clojure.lang.Compiler;
import clojure.lang.RT;

public class Test {

public static void main(String(link: ) args) {
    RT.var("clojure.core", "require");
    String s = "(let (link: mumble (new java.io.StringReader \"\")) (. mumble close))";
    Compiler.load(new StringReader(s));
}

}

应该很清楚,点操作符中的'mumble'引用的是局部定义的mumble。然而,如果我们定义一个名为'mumble'的类在默认包中,Clojure会拾取那个类。

为了防止有任何异议:是的,我们知道将类放在默认包中是极差的做法。问题的关键在于,Java生态系统极其多样化,有很多人可能无法控制许多JAR文件。虽然有人可能会争论,“不要在默认命名空间中放置类”,但问题的关键是,Clojure在这里犯了错误,这种情况下会在实际中产生,而并非由于实施者的过错。

5 个答案

0

评论者:ezyang

这是一个暂时性的补丁,使得这种错误不太可能发生。

0

评论者:jafingerhut

爱德华,Rich Hickey的政策仅考虑将那些签署了贡献协议的人编写的Clojure补丁包括在内:[https://clojure.org/contributing

你对成为贡献者感兴趣吗?

0

评论者:ezyang

当然,但是附上的补丁绝对不是你想实际应用的补丁,因为它只是治标不治本。

0

评论者:jafingerhut

我不太确定,但这个工单可能与CLJ-1171有关。至少,那里的问题是一个全局名称 不是 由let绑定的地方被局部名称遮蔽。这听起来和这个问题很相似。

0
...