如何在Leiningen生成的jar中调试静态初始化程序错误?

时间:2016-09-14 18:26:12

标签: clojure

在我的Clojure库testlib中,我有一个带有:gen-class指令的命名空间,如下所示:

(ns com.some_long_path.NewClass
  (:import (java.util List ArrayList))
  (:gen-class
     :name com.some_long_path.NewClass
     :methods [^{:static true} [getValues [String] java.util.List]]
  )
  (:require
    [testlib.core :refer [var1 var2]]))

(defn getValues [^String]
  (java.util.ArrayList. [3 5]))

如果我在import项目中的另一个命名空间内尝试testlib此类(在调用compile之后),我可以无错误地调用getValues方法。

但是,如果我lein install,请在另一个项目testlib中加入jartest,然后在下面的测试名称空间中使用它

(ns jartest.core
  (:import [com.some_long_path NewClass]))

(NewClass.)
(NewClass/getValues "some string")

调用NewClass构造函数会产生异常

CompilerException java.lang.NoClassDefFoundError: Could not initialize class com.some_long_path.NewClass

getValues因此给出了

CompilerException java.lang.IllegalStateException: Attempting to call unbound fn: #'com.some_long_path.NewClass/getValues

但是,如果我从上面的require命名空间定义中删除NewClass,则代码甚至可以在另一个库中运行。所以问题是由一些缺少的依赖项引起的,尽管我确保testlib中的所有依赖项也包含在jartest中,并且testlib.core名称空间是AOT编译的。

另外,我已经尝试反编译生成的com.some_long_path.NewClass类文件,并且有一个静态初始化程序块,如下所示:

static
{
  Util.loadWithClass("/com/some_long_path/NewClass", NewClass.class);
}

很可能上述错误是从loadWithClass内引发的。但我怎么知道到底出了什么问题呢?

谢谢!

更新:我能够通过二进制搜索错误找出我需要的命名空间中的错误(注释掉代码直到事情再次起作用)。事实证明,slurp中的resources文件夹中的某些文件是testlib,但jartest项目中没有这些文件。更改代码以使用clojure.java.io/resource解决了问题。然而,问题仍然存在 - 如何在不诉诸蛮力方法的情况下确切地找出问题所在?

1 个答案:

答案 0 :(得分:1)

这是必须的答案 - 没有更好的方法,没有更深入地理解依赖树,这通常只能通过评论东西并看到现在有效的方式来完成。这是我从clojure和使用gen-class进行java类加载的经验。

Heres希望这不是最高投票的答案。