【问题标题】:NoClassDefFoundError on a protocol when requiring its namespace需要命名空间时协议上的 NoClassDefFoundError
【发布时间】:2011-05-14 16:49:45
【问题描述】:

这是我得到的异常的秘诀(编辑:ProtoImpl 在另一个 ns 中定义,我将省略它以简化描述):

myns.clj

(ns myns)

(defprotocol Proto
  (func [this]))

(extend-protocol Proto
  ProtoImpl
  (func [this] (do-something ...)))

interop.clj

(ns interop
  (:require [myns :as m]))

(defn startup
  []
  (m/func (ProtoImpl.)))

(gen-class :name interop.Interop
           :prefix "interop-"
           :methods [[boot [] void]])

(defn interop-boot
  [this]
  (startup)))

myns.clj 和 interop.clj 都在 webapp 中提供,后者也是 AOT 编译的,因此可以立即在类路径中生成 Interop.class。这被实例化为 Spring bean。

当 webapp 启动时,它无法引导并出现以下异常:

[...]
    at myns__init.load(Unknown Source)
    at myns__init.<clinit>(Unknown Source)
[...]
    at interop.Interop.<clinit>(Unknown Source)
[...]
Caused by: NoClassDefFoundError: myns.Proto

什么会导致这个问题?


编辑:我无法再重现该错误,我重新编译并重新运行应用程序,该应用程序启动时完美无缺……我仍然很想了解在哪些情况下会出现此类问题向上。

在我看来,类加载器找不到Proto 的类定义,我认为这是 clojure RT 的作用,在解析相关的 .clj 源文件后立即加载。正如您在我收到的堆栈跟踪的摘录中看到的那样,正在加载 myns,并且它恰好在那里定义了 Proto。我怎么有NoClassDefFoundError

【问题讨论】:

    标签: java spring interop clojure classloader


    【解决方案1】:

    应该导入 Clojure 记录。以下应该有效:

    (ns interop
      (:require [myns :as m])
      (:import  myns.Proto))
    

    【讨论】:

    • interop 命名空间内没有直接引用Proto,我为什么要:import 呢?
    • 此外,NoClassDefFoundError 是个例外,这意味着类加载器找不到 Proto 的 .class 定义。如果问题是我忘记了import 协议,我会期待类似java.lang.Exception: Unable to resolve symbol: Proto in this context (interop.clj:&lt;...&gt;)
    • 我无法重现该问题,即使答案与问题没有直接关系,指出在 Clojure 中使用 Prototype 需要什么总是值得的,我只是接受它:-)
    【解决方案2】:

    我遇到了同样的问题。在我的project.clj 中将这两个类添加到:aot 解决了这个问题。你的project.clj 会是这样的::aot [myns interop]

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多