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

欢迎!请参阅关于页面了解有关如何使用本网站的更多信息。

+1
Clojure
已关闭

我在J9 JVM上的Clojure上遇到麻烦。

我对J9感兴趣,希望Clojure不会限制虚拟机选择。

麻烦发生在Windows和Linux上,并且发生在J9 JVM的"11"和"15"版本以及包括1.10.1、1.10.2、1.7和1.5.1在内的许多(所有?)Clojure版本中。

问题是一个或另一个类型的异常或错误,通常起源于clojure.core;通常它是一个在reduce1中出现的荒谬NullPointerException,这也由Leiningen在J9 JVM上抛出。

问题是不可预测的。但如果J9"始终编译"(-Xcomp),则可靠地出错,而当J9"始终解释"(-Xint)时似乎正常。由于某些原因,该报告中给出的clojure命令似乎不尊重琼选项,所以我修改了clojure脚本来传递此实验所需的必要JVM选项。

我使用

./linux-install-1.10.2.774.sh --prefix ${HOME}/clo

我从一个名为adoptopenjdk.org网站的Linux系统安装了AdoptOpenJDK版本11的J9 JVM。

在第一次运行clojure

${HOME}/clo/bin/clojure

它抛出NullPointerException。更多关于这一点的内容见下文。

尝试各种JVM选项,我发现-Xint JVM选项允许clojure下载各种事物并显示REPL提示符。根据java -X,此选项意味着"仅解释模式执行"。要使用-Xint,我已修改clojure以传递JVM选项。(并非clojure的所有Java调用的选项都受到尊敬。)

第一次成功运行后,后续的clojure运行通常成功地产生REPL提示符。

然而,-Xcomp JVM选项每次都会导致错误。这意味着"要求在第一次调用时编译方法"。

我第一次在使用Leiningen 2.9.5的Windows版本时遇到J9问题。我的发现部分路径在Git组件的问题报告中:[https://github.com/technomancy/leiningen/issues/2725](https://github.com/technomancy/leiningen/issues/2725)

NullPointerException堆栈跟踪为

Exception in thread "main" java.lang.NullPointerException
	at clojure.core.protocols$naive_seq_reduce.invokeStatic(protocols.clj:62)
	at clojure.core.protocols$interface_or_naive_reduce.invokeStatic(protocols.clj:72)
     ...
	at clojure.pprint$pprint.invoke(pprint_base.clj:241)
	at clojure.lang.Var.invoke(Var.java:384)
	at clojure.main$report_error$fn__9186$fn__9187.invoke(main.clj:603)
	at clojure.main$report_error$fn__9186.invoke(main.clj:602)
	at clojure.main$report_error.invokeStatic(main.clj:601)
	at clojure.main$main.invokeStatic(main.clj:666)
	at clojure.main$main.doInvoke(main.clj:616)
	at clojure.lang.RestFn.applyTo(RestFn.java:137)
	at clojure.lang.Var.applyTo(Var.java:705)
	at clojure.main.main(main.java:40)

在随后的运行中,我遇到了另一个错误

Syntax error macroexpanding clojure.core/defn- at (clojure/tools/cli.cljc:124:1).
null
 Full report at:
/tmp/clojure-12652663517358293277.edn

该文件说

{:clojure.main/message
 "Syntax error macroexpanding clojure.core/defn- at (clojure/tools/cli.cljc:124:1).\nnull\n",
 :clojure.main/triage
 {:clojure.error/phase :macro-syntax-check,
  :clojure.error/line 124,
  :clojure.error/column 1,
  :clojure.error/source "cli.cljc",
  :clojure.error/symbol clojure.core/defn-,
  :clojure.error/path "clojure/tools/cli.cljc",
  :clojure.error/class java.lang.NullPointerException},
 :clojure.main/trace
 {:via
  [{:type clojure.lang.Compiler$CompilerException,
    :message
    "Syntax error macroexpanding clojure.core/defn- at (clojure/tools/cli.cljc:124:1).",
    :data
    {:clojure.error/phase :macro-syntax-check,
     :clojure.error/line 124,
     :clojure.error/column 1,
     :clojure.error/source "clojure/tools/cli.cljc",
     :clojure.error/symbol clojure.core/defn-},
    :at [clojure.lang.Compiler checkSpecs "Compiler.java" 6976]}
   {:type java.lang.NullPointerException,
    :at [clojure.core$every_QMARK_ invokeStatic "core.clj" 2683]}],
  :trace
  [[clojure.core$every_QMARK_ invokeStatic "core.clj" 2683]
   [clojure.core$every_QMARK_ invoke "core.clj" 2676]
   [clojure.spec.alpha$pcat_STAR_ invokeStatic "alpha.clj" 1388]
   [clojure.spec.alpha$pcat_STAR_ invoke "alpha.clj" 1387]
   [clojure.spec.alpha$deriv invokeStatic "alpha.clj" 1542]
   [clojure.spec.alpha$deriv invoke "alpha.clj" 1528]
   [clojure.spec.alpha$re_conform invokeStatic "alpha.clj" 1669]
   [clojure.spec.alpha$re_conform invoke "alpha.clj" 1660]
   [clojure.spec.alpha$regex_spec_impl$reify__2510
    conform_STAR_
    "alpha.clj"
    1710]
   [clojure.spec.alpha$conform invokeStatic "alpha.clj" 171]
   [clojure.spec.alpha$conform invoke "alpha.clj" 167]
   [clojure.spec.alpha$macroexpand_check invokeStatic "alpha.clj" 708]
   [clojure.spec.alpha$macroexpand_check invoke "alpha.clj" 704]
   [clojure.lang.AFn applyToHelper "AFn.java" 156]
   [clojure.lang.AFn applyTo "AFn.java" 144]
   [clojure.lang.Var applyTo "Var.java" 705]
   [clojure.lang.Compiler checkSpecs "Compiler.java" 6974]
   [clojure.lang.Compiler macroexpand1 "Compiler.java" 6992]
   [clojure.lang.Compiler macroexpand "Compiler.java" 7079]
   [clojure.lang.Compiler eval "Compiler.java" 7165]
   [clojure.lang.Compiler load "Compiler.java" 7640]
   [clojure.lang.RT loadResourceScript "RT.java" 381]
   [clojure.lang.RT loadResourceScript "RT.java" 372]
   [clojure.lang.RT load "RT.java" 459]
   [clojure.lang.RT load "RT.java" 424]
   [clojure.core$load$fn__6857 invoke "core.clj" 6115]
   [clojure.core$load invokeStatic "core.clj" 6114]
   [clojure.core$load doInvoke "core.clj" 6098]
   [clojure.lang.RestFn invoke "RestFn.java" 408]
   [clojure.core$load_one invokeStatic "core.clj" 5897]
   [clojure.core$load_one invoke "core.clj" 5892]
   [clojure.core$load_lib$fn__6797 invoke "core.clj" 5937]
   [clojure.core$load_lib invokeStatic "core.clj" 5936]
   [clojure.core$load_lib doInvoke "core.clj" 5917]
   [clojure.lang.RestFn applyTo "RestFn.java" 142]
   [clojure.core$apply invokeStatic "core.clj" 669]
   [clojure.core$load_libs invokeStatic "core.clj" 5974]
   [clojure.core$load_libs doInvoke "core.clj" 5958]
   [clojure.lang.RestFn applyTo "RestFn.java" 137]
   [clojure.core$apply invokeStatic "core.clj" 669]
   [clojure.core$require invokeStatic "core.clj" 5996]
   [clojure.core$require doInvoke "core.clj" 5996]
   [clojure.lang.RestFn invoke "RestFn.java" 619]
   [clojure.tools.deps.alpha.script.make_classpath2$eval140$loading__6738__auto____141
    invoke
    "make_classpath2.clj"
    9]
   [clojure.tools.deps.alpha.script.make_classpath2$eval140
    invokeStatic
    "make_classpath2.clj"
    9]
   [clojure.tools.deps.alpha.script.make_classpath2$eval140
    invoke
    "make_classpath2.clj"
    9]
   [clojure.lang.Compiler eval "Compiler.java" 7181]
   [clojure.lang.Compiler eval "Compiler.java" 7170]
   [clojure.lang.Compiler load "Compiler.java" 7640]
   [clojure.lang.RT loadResourceScript "RT.java" 381]
   [clojure.lang.RT loadResourceScript "RT.java" 372]
   [clojure.lang.RT load "RT.java" 459]
   [clojure.lang.RT load "RT.java" 424]
   [clojure.core$load$fn__6857 invoke "core.clj" 6115]
   [clojure.core$load invokeStatic "core.clj" 6114]
   [clojure.core$load doInvoke "core.clj" 6098]
   [clojure.lang.RestFn invoke "RestFn.java" 408]
   [clojure.core$load_one invokeStatic "core.clj" 5897]
   [clojure.core$load_one invoke "core.clj" 5892]
   [clojure.core$load_lib$fn__6797 invoke "core.clj" 5937]
   [clojure.core$load_lib invokeStatic "core.clj" 5936]
   [clojure.core$load_lib doInvoke "core.clj" 5917]
   [clojure.lang.RestFn applyTo "RestFn.java" 142]
   [clojure.core$apply invokeStatic "core.clj" 669]
   [clojure.core$load_libs invokeStatic "core.clj" 5974]
   [clojure.core$load_libs doInvoke "core.clj" 5958]
   [clojure.lang.RestFn applyTo "RestFn.java" 137]
   [clojure.core$apply invokeStatic "core.clj" 669]
   [clojure.core$require invokeStatic "core.clj" 5996]
   [clojure.main$main_opt invokeStatic "main.clj" 514]
   [clojure.main$main_opt invoke "main.clj" 510]
   [clojure.main$main invokeStatic "main.clj" 664]
   [clojure.main$main doInvoke "main.clj" 616]
   [clojure.lang.RestFn applyTo "RestFn.java" 137]
   [clojure.lang.Var applyTo "Var.java" 705]
   [clojure.main main "main.java" 40]],
  :phase :macro-syntax-check}}

在进一步的运行中,我得到了另一个错误消息

Exception in thread "main" java.lang.NullPointerException
	at clojure.core$reduce1.invokeStatic(core.clj:944)
	at clojure.core$reduce1.invokeStatic(core.clj:936)
	at clojure.core$merge.invokeStatic(core.clj:3052)
	at clojure.core$Throwable__GT_map$base__7474.invoke(core_print.clj:491)
	at clojure.core$map$fn__5885.invoke(core.clj:2757)
	at clojure.lang.LazySeq.sval(LazySeq.java:42)
	at clojure.lang.LazySeq.seq(LazySeq.java:51)
	at clojure.lang.RT.seq(RT.java:535)
	at clojure.lang.LazilyPersistentVector.create(LazilyPersistentVector.java:44)
	at clojure.core$vec.invokeStatic(core.clj:379)
	at clojure.core$Throwable__GT_map.invokeStatic(core_print.clj:492)
	at clojure.main$report_error.invokeStatic(main.clj:593)
	at clojure.main$main.invokeStatic(main.clj:666)
	at clojure.main$main.doInvoke(main.clj:616)
	at clojure.lang.RestFn.applyTo(RestFn.java:137)
	at clojure.lang.Var.applyTo(Var.java:705)
	at clojure.main.main(main.java:40)

Clojure 1.5.1中也可以重现这个问题

$ java -Xcomp -cp clojure-1.5.1.jar clojure.main
Exception in thread "main" java.lang.ExceptionInInitializerError
	at java.base/java.lang.J9VMInternals.ensureError(J9VMInternals.java:185)
	at java.base/java.lang.J9VMInternals.recordInitializationFailure(J9VMInternals.java:174)
	at java.base/java.lang.Class.forNameImpl(Native Method)
	at java.base/java.lang.Class.forName(Class.java:413)
	at clojure.lang.RT.loadClassForName(RT.java:2098)
	at clojure.lang.RT.load(RT.java:430)
	at clojure.lang.RT.load(RT.java:411)
	at clojure.core$load$fn__5018.invoke(core.clj:5530)
	at clojure.core$load.doInvoke(core.clj:5529)
	at clojure.lang.RestFn.invoke(RestFn.java:408)
	at clojure.core$load_one.invoke(core.clj:5336)
	at clojure.core$load_lib$fn__4967.invoke(core.clj:5375)
	at clojure.core$load_lib.doInvoke(core.clj:5374)
	at clojure.lang.RestFn.applyTo(RestFn.java:142)
	at clojure.core$apply.invoke(core.clj:619)
	at clojure.core$load_libs.doInvoke(core.clj:5413)
	at clojure.lang.RestFn.applyTo(RestFn.java:137)
	at clojure.core$apply.invoke(core.clj:619)
	at clojure.core$require.doInvoke(core.clj:5496)
	at clojure.lang.RestFn.invoke(RestFn.java:408)
	at clojure.lang.Var.invoke(Var.java:415)
	at clojure.main.main(main.java:36)
Caused by: java.lang.NullPointerException
	at clojure.core$reduce1.invoke(core.clj:896)
	at clojure.core$expand_method_impl_cache.invoke(core_deftype.clj:474)
	at clojure.core$_cache_protocol_fn.invoke(core_deftype.clj:542)
	at clojure.core.protocols$fn__5979$G__5974__5992.invoke(protocols.clj:13)
	at clojure.core$reduce.invoke(core.clj:6177)
	at clojure.core$into.invoke(core.clj:6229)
	at clojure.main__init.load(Unknown Source)
	at clojure.main__init.<clinit>(Unknown Source)
已关闭,备注为:J9中存在一个bug,目前已修复

3 个回答

+2

选择了
 
最佳答案

有兴趣的人可以在这里找到J9 bug报告: https://github.com/eclipse/openj9_issues/12191(感谢Ghadi!)

问题追踪到j9中的一个错误变更,并已回滚(见https://github.com/eclipse/openj9_issues/12191#issuecomment-799695842)。

从解决方案中

"提交回滚到版本#12221将该修复回归到0.26版本,该版本将用于生成Java 8、11和16。我们对所有这些JVM级别使用相同的JIT编译器,因此修复将在0.26版本中。

本次发布计划于2021年4月23日
https://projects.eclipse.org/projects/technology.openj9/releases/0.26.0 "
0

在过去一周中,在Slack上就J9 JVM的问题进行了很多讨论,共识似乎是Clojure与其不兼容(未对其进行测试)。我只是搜索了一下J9,就找到了一打人报告了在多个频道中J9 JVM的随机行为。

在火灾情况下,身处有两个出口的地方会更好。有两个人流认证的 JVM 也是这样。你不必每年都尝试火警通道。但,如果你尝试了火警通道,发现它是锁着的,哎呀。尤其是在其他人都能正常使用火警通道的情况下,它似乎只对你锁着,可能是因为你特殊的脑植入。

我将此事提交在此,是为了提供详细信息以启动 Jira 问题。这是我们确立有利于发现解决方案或清晰的向上游漏洞报告的条件的方式。

在 J9 版本 11 & 15 中,“reduce1”作为直接原因被提及,这在 Clojure 版本 1.5.1 以上版本中尤为常见,这使得我希望失败可以被缩小,或者能够找到解决方案,或者将问题提交给 J9 的修复人员。
我认为“reduce1”并没有什么特殊,更有可能是因为它几乎是在 JVM 中运行的第一个懒惰序列代码。如果 npe 与 Clojure 编译器发出的本地清除字节码有关,这并不奇怪,这在 Java -> JVM 方面并不常见,并且涉及到大多数遍历懒惰序列的功能。
这是一个有希望的理论。还有一个堆栈跟踪,其中问题发生在“some”中。
我在上面提供了链接,但不清楚人们具体通知了什么 - https://github.com/eclipse/openj9/issues/12191
他们只在他们的系统中发现了一个导致此问题的具体问题: https://github.com/eclipse/openj9/issues/12191#issuecomment-797840254

Alex的最初猜测果然没错 :-) - 问题并不出在Clojure本身。

还有其他更微妙的问题,比如哈希函数之间微小的差异 - 看这篇文章的结尾: https://www.royvanrijn.com/blog/2018/05/openj9-jvm-shootout/

这些微妙的问题在各个依赖项中很难找到。我的观点是,重点关注OpenJDK-16的一些重要部分 - 这至少在我们的东西上显示出一些令人印象深刻的性能改进 - 将产生更大的回报。
Clojure对特定的哈希值没有保证,因此我认为哈希值的不同本身不是一个问题(只要保证总体上保持一致 - 相等的东西应该有相同的哈希代码)。
我同意Clojure本身会很好运行(至于techascent系统中的每个项目也是如此);这和我上面的一个观点相同。我个人关心的是JVM生态系统中的所有其他可能的依赖项。

主要是我对你的第一次尝试就得到了结果印象深刻 :-)。
0
by
他们在 openj9-0.26.0 中修复了这个问题!感谢 Clojure Squads 缩小了问题范围,并且与 Eclipse 编译器编写者一起追究问题!
...