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

Clojure中gen-class生成类引发ClassNotFoundException的解决方法

解决Clojure gen-class生成类的ClassNotFoundException问题

问题场景

使用gen-class在myorg.helpers.fs-input-stream命名空间生成myorg.helpers.FsInputStream类,在myorg.plugin.orc-output中导入该类,运行测试时抛出:

Syntax error (ClassNotFoundException) compiling at (myorg/plugin/orc_output.clj:1:1).
myorg.helpers.fs-input-stream.FsInputStream

相关代码如下:

生成类的命名空间代码:

(ns myorg.helpers.fs-input-stream)
(gen-class
 :name "myorg.helpers.FsInputStream"
 :extends java.io.ByteArrayInputStream
 :implements [org.apache.hadoop.fs.Seekable org.apache.hadoop.fs.PositionedReadable]
 :main false
 :exposes {buf  {:get getBuf}
           pos  {:get getPos}
           mark {:get getMark}}
 :init-impl-ns false)

使用类的命名空间代码:

(ns myorg.plugin.orc-output
  (:import
   (myorg.helpers FsInputStream)
   (org.apache.hadoop.fs FileSystem FSDataInputStream)))

(set! *warn-on-reflection* true)

(defn input-stream-filesystem [buffered-bytes]
  (proxy [FileSystem] []
    (open [_]
      (FSDataInputStream. (FsInputStream. buffered-bytes)))))

测试代码:

(ns myorg.plugin.orc-output-test
  (:require [clojure.test :refer :all])
  (:require [myorg.plugin.orc-output :refer :all]))

(deftest orc-create
  (is (= 1 1)))

核心原因

gen-class生成的Java类需要**提前编译(AOT)**才能被其他命名空间导入使用。测试运行时,生成类的命名空间未被提前加载编译,导致JVM找不到对应的类文件。

解决步骤

1. 配置AOT编译

在项目构建配置中,将生成类的命名空间标记为需要AOT编译:

  • 若使用Leiningen(project.clj):
    添加:aot配置项:
    (defproject gen-class-error-demo "0.1.0-SNAPSHOT"
      :dependencies [[org.clojure/clojure "1.11.1"]
                     [org.apache.hadoop/hadoop-common "3.3.4"]]
      :aot [myorg.helpers.fs-input-stream]) ; 指定要AOT编译的命名空间
    
  • 若使用tools.deps(deps.edn):
    添加:aot配置并定义编译任务:
    {:deps {org.clojure/clojure {:mvn/version "1.11.1"}
            org.apache.hadoop/hadoop-common {:mvn/version "3.3.4"}}
     :aliases {:compile {:exec-fn clojure.core/compile
                         :exec-args {:namespace myorg.helpers.fs-input-stream}}}}
    
    运行命令手动编译:clj -X:compile

2. 调整测试的依赖加载顺序

在测试命名空间中,先require生成类的命名空间,确保它被加载并触发类生成:
修改测试代码:

(ns myorg.plugin.orc-output-test
  (:require [clojure.test :refer :all]
            [myorg.helpers.fs-input-stream] ; 优先加载生成类的命名空间
            [myorg.plugin.orc-output :refer :all]))

(deftest orc-create
  (is (= 1 1)))

3. IDE运行配置调整

在IntelliJ IDEA中:

  • 打开测试的运行配置,勾选**"Compile before launch"**选项,确保测试前完成所有必要编译。
  • 或者,将myorg.helpers.fs-input-stream命名空间添加到编译前置列表中。

验证

完成上述配置后,重新运行测试,ClassNotFoundException即可解决。

内容的提问来源于stack exchange,提问作者user51

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 23:10:40