使用insn生成Java字节码测试:lein test执行异常求助
问题解决建议
可能的原因
- 类加载器不一致:Cider和lein test使用的类加载器环境不同,导致生成的字节码类未被lein test的上下文正确加载,调用的main方法并非你生成的版本。
- 输出流不匹配:Clojure的
with-out-str捕获的是Clojure的*out*变量,但Java的System.out在lein test环境下未与*out*绑定,导致输出无法被捕获。 - Eval上下文差异:
eval在不同环境下的命名空间、类路径上下文不同,可能无法定位到生成的类。
具体解决方案
方案1:统一Java输出流与Clojure的out
修改测试代码,将Java的System.out临时重定向到Clojure的输出流,确保输出被with-out-str捕获:
(deftest sum-bt-test (let [cname 'my.pkg.Test _ (sum-bt 4) original-out System/out] (try ;; 绑定Java输出流到Clojure的*out* (System/setOut (java.io.PrintStream. (clojure.java.io/writer *out*))) (let [result (with-out-str (eval `(. ~cname main)))] (is (= result "8\n"))) (finally ;; 恢复原输出流 (System/setOut original-out)))))
方案2:用反射调用替代eval
避开eval的上下文干扰,直接通过反射调用生成类的main方法:
(deftest sum-bt-test (let [_ (sum-bt 4) clazz (Class/forName "my.pkg.Test") main-method (.getMethod clazz "main" (into-array Class [])) result (with-out-str (System/setOut (java.io.PrintStream. (clojure.java.io/writer *out*))) (.invoke main-method nil (into-array Object [])))] (is (= result "8\n"))))
方案3:指定类加载器生成类
确保生成的类被加载到当前上下文的类加载器中,修改make函数:
(defn make [& {:as m}] (insn/new-instance (merge m {:classloader (clojure.lang.RT/baseLoader)})))
验证顺序
优先尝试方案1(最常见的输出捕获问题),若无效再尝试方案2(排除eval干扰),最后尝试方案3(类加载器问题)。
内容的提问来源于stack exchange,提问作者Édipo Féderle
相关产品推荐
相关产品推荐

