请在 Clojure 2024 调查问卷!中分享您的想法。

欢迎!有关本网站如何运作的更多信息,请参阅关于页面。

0
工具 namespace
重贴标签

如果我用任何 jar 文件调用 find-ns-decls-in-jarfile jarfile(以下示例),我都会遇到这个异常

在 clojure.tools.namespace.find/read-ns-decl-from-jarfile-entry (find.clj:158) 处打印返回值时出错(ClassCastException)。
无法将 java.util.jar.JarFile 类型转换为 java.io.File 类型(java.util.jar.JarFile 和 java.io.File 都位于 'bootstrap' 加载器的 java.base 模块中)

我可以使用以下示例重现这个问题


    (let [filename (format "%s/.m2/repository/org/clojure/tools.namespace/1.4.2/tools.namespace-1.4.2.jar" (System/getenv "HOME"))
      jarfile (JarFile. (io/file filename))]
  (clojure.tools.namespace.find/find-ns-decls-in-jarfile jarfile))

我认为问题描述在 第 159 行的类型提示。我认为它应该改为 ^java.util.jar.JarFile

by
如果这有帮助,我还创建了一个补丁(包括修复代码风格问题)。如果需要,我很乐意签署贡献者协议。

<pre>
<code>
diff --git a/src/main/clojure/clojure/tools/namespace/find.clj b/src/main/clojure/clojure/tools/namespace/find.clj
index 88f88ef..d67aaf1 100644
--- a/src/main/clojure/clojure/tools/namespace/find.clj
+++ b/src/main/clojure/clojure/tools/namespace/find.clj
@@ -12,12 +12,10 @@
   clojure.tools.namespace.find
   (:require [clojure.java.classpath :as classpath]
             [clojure.java.io :as io]
-            [clojure.set :as set]
             [clojure.tools.namespace.file :as file]
             [clojure.tools.namespace.parse :as parse])
-  (:import (java.io File FileReader BufferedReader PushbackReader
-                    InputStreamReader)
-           (java.util.jar JarFile JarEntry)))
+  (:import (java.io File PushbackReader)
+           (java.util.jar JarFile)))
 
 (set! *warn-on-reflection* true)
 
@@ -92,7 +90,7 @@
            (let [[_ nom & more :as decl] (file/read-file-ns-decl % (:read-opts platform))]
              (when (and decl nom (symbol? nom))
                (list* 'ns (with-meta nom
-                            {:dir (.getName ^java.io.File dir) :file (.getName ^java.io.File %)})
+                       {:dir (.getName ^File dir) :file (.getName ^File %)})
                       more))))
        (find-sources-in-dir dir platform))))
 
@@ -156,7 +154,7 @@
        (ignore-reader-exception
         (let [[_ nom & more] (parse/read-ns-decl rdr read-opts)]
           (list* 'ns (with-meta nom
-                       {:jar (.getName ^java.io.File jarfile) :file entry-name})
+                       {:jar (.getName ^JarFile jarfile) :file entry-name})
                  more)))))))
 
 (defn find-ns-decls-in-jarfile

1个答案

0
谢谢修正。顺便说一句,我认为我发现了另一个问题。如果我在类路径上运行jars,通过`find-namespaces`会得到类似以下错误的错误

<pre>
<code>
打印返回值时发生错误(NullPointerException)在 clojure.core/with-meta (core.clj:220)。
无法调用 "clojure.lang.IObj.withMeta(clojure.lang.IPersistentMap)" 因为 "x" 为 null



我认为出现的问题可能是 `read-ns-decl` 函数有时未能返回一个命名空间声明(例如,正在读取的文件是 project.clj,所以不在一个命名空间内),然后 `nom` 在返回的 let 绑定中变为 `nil`。这使得调用 `with-meta nom` 时出现问题。

因此,我认为第 157 行的 `(let [[_ nom & more] (parse/read-ns-decl rdr read-opts)]...)` 形式只需改为 `when-let`。我在本地分支中做了这个更改,并且它运行正常。

谢谢!

顺便提一下,下面是一个使用来自本地 m2 目录的 Clojure jar 的示例 REPL 会话

<pre>
<code>
;; 使用现有的 1.4.3 实现
加载 src/main/clojure/clojure/tools/namespace/find.clj... 完成
(find-namespaces [(io/file "/Users/mbastian/.m2/repository/amalloy/ring-buffer/1.3.1/ring-buffer-1.3.1.jar")])
打印返回值时发生错误(NullPointerException)在 clojure.core/with-meta (core.clj:220)。
无法调用 "clojure.lang.IObj.withMeta(clojure.lang.IPersistentMap)" 因为 "x" 为 null
;; 使用 when-let
加载 src/main/clojure/clojure/tools/namespace/find.clj... 完成
(find-namespaces [(io/file "/Users/mbastian/.m2/repository/amalloy/ring-buffer/1.3.1/ring-buffer-1.3.1.jar")])
=> (amalloy.ring-buffer)

by
谢谢!我还在 `JarFile` 类型提示的修复中也解决了这个问题,这两个都会在下一个版本中推出。
by
太好了,谢谢!
...