简体   繁体   中英

How to debug static initialiser errors in jars generated by Leiningen?

in my Clojure library testlib , i've got a namespace with a :gen-class directive that looks like this:

(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]))

If i try to import this class inside another namespace in the testlib project (after invoking compile ), i can invoke getValues method without errors.

However, if i lein install , include testlib in another project jartest , and then use it in a test namespace below

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

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

invoking NewClass constructor gives an exception

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

and getValues as a consequence gives

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

However, if i remove the require s from NewClass namespace definition above, the code works even in another library. So the problem is caused by some missing dependencies, although i've made sure that all dependencies of testlib are also included in jartest , and that testlib.core namespace is AOT-compiled.

Also, i've tried decompiling generated com.some_long_path.NewClass class file, and there is a static initializer block that looks like this:

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

Most probably the above-mentioned error is thrown from within loadWithClass . But how do i find out what exactly is wrong?

Thanks!

UPDATE: I was able to figure out what was wrong in the namespace i was requiring through a binary search for errors (commenting out code until things worked again). It turned out that some files were slurp ed from resources folder in testlib , but they were not present in jartest project. Changing the code to use clojure.java.io/resource fixed the problem. However, the question still stands - how to find out exactly what was the problem, without resorting to brute force methods?

Here is the obligatory answer- there isnt a better way, without understanding the dependency tree more deeply, which often can only be done by commenting stuff out and seeing what now works. That has been my experience with java classloading from clojure and using gen-class.

Heres hoping this isnt the highest voted answer.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM