为何sbt控制台报ClassNotFoundException而Scala REPL正常?
原因分析
核心问题出在类加载器的差异:
- 直接用
scala命令启动的REPL默认采用系统类加载器,能直接访问JDK自带的java.sql包类; - sbt console使用的是Scala 3(Dotty)的
AbstractFileClassLoader,这个类加载器的委托逻辑存在问题,没有优先委托父类加载器查找JDK系统类,导致无法定位java.sql.Connection。
另外,Java 9+的模块化系统也有影响:java.sql属于JDK系统模块,但空项目下的sbt console没有自动配置对该模块的依赖,进一步阻碍了类加载。
解决方案
方式一:临时解决(在sbt console中直接调整)
不用Class.forName,改用当前线程的上下文类加载器加载类:
Thread.currentThread().getContextClassLoader().loadClass("java.sql.Connection")
这种方式会绕过sbt的隔离类加载器,直接调用系统类加载器查找JDK自带类。
方式二:项目级永久解决
在build.sbt中添加以下配置:
- 显式声明JDK模块依赖:
javaOptions += "--add-modules java.sql" - 配合类加载策略配置(确保类加载器层级更扁平):
classLoaderLayeringStrategy := ClassLoaderLayeringStrategy.Flat
修改后重启sbt console,即可正常执行Class.forName("java.sql.Connection")。
内容的提问来源于stack exchange,提问作者Adam Mackler
相关产品推荐
相关产品推荐

