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

欢迎!请查看关于页面获取更多关于如何使用此工程的信息。

0
Clojure

这个错误的明显症状是在您的类路径中有一个名为“w”的类(默认包)并尝试加载Clojure的核心类。例如

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

(其中hotspotapi.jar是一个被混淆的JAR的典型例子)导致

线程"main"中发生异常 java.lang.ExceptionInInitializerError

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

原因:找不到字段:close,在编译:(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

原因:找不到字段: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修改:[a rel="nofollow" href="https://clojure.org/contributing" target="_blank">https://clojure.org/contributing

你是否有兴趣成为贡献者?

0

由ezyang发表的评论

当然,尽管附带的补丁明确定不是你要实际应用的,因为它只是临时解决问题的。

0

由jafingerhut发表的评论

我不确定,但这个工单可能与CLJ-1171有关。至少,那里的问题是全局名称没有被用let绑定的地方的局部名称所阴影。这看起来与这个问题很相似。

0
参考:[a href="https://clojure.atlassian.net/browse/CLJ-1016" rel="nofollow" target="_blank">https://clojure.atlassian.net/browse/CLJ-1016
...