You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用insn生成Java字节码测试:lein test执行异常求助

问题解决建议

可能的原因

  1. 类加载器不一致:Cider和lein test使用的类加载器环境不同,导致生成的字节码类未被lein test的上下文正确加载,调用的main方法并非你生成的版本。
  2. 输出流不匹配:Clojure的with-out-str捕获的是Clojure的*out*变量,但Java的System.out在lein test环境下未与*out*绑定,导致输出无法被捕获。
  3. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 21:15:07