如何从 Clojure 程序中访问 JAR 类?

Gre*_*ams 5 java compilation clojure noclassdeffounderror

我已经被困在一件我知道我以前曾经做过的事情上好几天了。我可能错过了一些明显的东西。任何帮助,将不胜感激。

在我的 Clojure 程序中,我想访问最初用 Java 编写的类中的方法。让我们使用一个具体的例子:org.infoml.jaxb.ObjectFactory。这些类位于 .jar 文件 ( infoml-classes-1.0.jar) 中,该文件是可双击的 Java 应用程序。如果打开 jar 文件,您会看到 Java 类包的顶级部分的文件夹:

macscooter:infoml-classes-1.0 folder gw$ find . -print | sed -e 's;[^/]*/;|____;g;s;____|; |;g'
.
|____META-INF
| |____MANIFEST.MF
|____org
| |____infoml
| | |____infocardOrganizer  <<<<<< Java application's classes
| | | |____AFileFilter.class

      |  ... many classes omitted here

| | | |____UniqueContentListener.class
| | | |____UniqueContentModel.class
| | |____jaxb
| | | |____AgentContainerLocationType.class
| | | |____AgentType.class

      |  ... many classes omitted here

| | | |____ObjectFactory.class   <<<<<< HERE IT IS

      |  ... many classes omitted here

| | | |____TableRowType.class
| | | |____TableType.class
macscooter:infoml-classes-1.0 folder gw$
Run Code Online (Sandbox Code Playgroud)

在我的 Clojure 程序中,我导入它(从文件cardmaker.clj):

(ns infwb.cardmaker
  (:gen-class)
  (:import
   (javax.xml.bind  JAXBContext  JAXBException  Marshaller
            Unmarshaller)
    (org.infoml.jaxb        ContentAgentContainerLocationType
            InfomlFile  InfomlType  ObjectFactory  PType  <<<<<< HERE IT IS
            RichTextWithExactType
            SelectorsType
            SimpleRichTextType)
   (java.io  ByteArrayOutputStream IOException)))
Run Code Online (Sandbox Code Playgroud)

当我打印出 REPL 看到的类路径时,它就在那里(如infoml-classes-1.0.jar):

infwb.cardmaker> (doseq [p (.getURLs (java.lang.ClassLoader/getSystemClassLoader))] (println (.getPath p)))
/Users/gw/tech/clojurestuff/cljprojects/infwb/src/
/Users/gw/tech/clojurestuff/cljprojects/infwb/test/
/Users/gw/tech/clojurestuff/cljprojects/infwb/classes/
/Users/gw/tech/clojurestuff/cljprojects/infwb/lib/clojure-1.3.0-SNAPSHOT.jar
/Users/gw/tech/clojurestuff/cljprojects/infwb/lib/clojure-contrib-1.2.0.jar
/Users/gw/tech/clojurestuff/cljprojects/infwb/lib/infoml-classes-1.0.jar  <<<<<< HERE IT IS
/Users/gw/tech/clojurestuff/cljprojects/infwb/lib/piccolo2dcore-1.3.jar
/Users/gw/tech/clojurestuff/cljprojects/infwb/lib/piccolo2dextras-1.3.jar
/Users/gw/tech/clojurestuff/cljprojects/infwb/lib/sxqj-beta2.jar
/Users/gw/tech/clojurestuff/cljprojects/infwb/lib/dev/clojure-1.2.0.jar
/Users/gw/tech/clojurestuff/cljprojects/infwb/lib/dev/swank-clojure-1.3.0-20110104.084027-21.jar
nil
infwb.cardmaker>
Run Code Online (Sandbox Code Playgroud)

但是,当我尝试编译文件 cardmaker.clj (通过 Cc Ck 或 )时(load-file "src/infwb/cardmaker.clj"),出现以下异常:

Could not initialize class org.infoml.jaxb.ObjectFactory
  [Thrown class java.lang.NoClassDefFoundError]
Run Code Online (Sandbox Code Playgroud)

我已经重新启动了我的机器,以尝试消除无意中的污垢作为问题的根源。我在互联网上研究了一些东西 - 没有运气。我查看了 MANIFEST.MF 文件以寻找线索,并将 jar 文件精简为我需要的类。我已经睡了两次了——仍然没有解决办法。

使用 Clojure 中现有的 Java 类是一件有用的事情。我很感激任何人能给我的帮助。谢谢。


附录:我的问题是由多种因素引起的,包括缺少 jar 文件。@kotarak 的回答很正确。谢谢。

kot*_*rak 1

你上课的方式import很好。显然,该类ObjectFactory无法初始化,因为它需要的其他一些类不在类路径上。查找完整的堆栈跟踪以找出缺少哪个类来ObjectFactory工作。(import 'org.infoml.jaxb.ObjectFactory)正如 @mikera 所建议的,您可以在 Repl 中使用来做到这一点。(除非 emacs 吃掉你的堆栈跟踪......)