升级Java 15与Eclipse 2020.12后FreeTTS运行报NoClassDefFoundError异常
问题核心定位
本次故障与Eclipse升级无关,核心诱因是Java 9及以上版本(你当前用的Java 15)新增的第三方包命名空间限制:
- Java 9引入模块化系统(JPMS)后,为防止第三方库冒充JDK内部API,默认禁止应用类加载器加载包名以
com.sun.开头的非JDK官方类 - FreeTTS的核心类(如
VoiceManager)恰好位于com.sun.speech.freetts.*包下,完全命中该限制 - SQLite的包名为
org.sqlite.*,不属于受限包范围,因此可正常加载,与你的现象完全匹配 - 旧版Java 8无此限制,因此相同代码可正常运行
解决方案(按操作复杂度排序)
1. 先排查Eclipse构建路径的低级错误
右键项目 → Build Path → Configure Build Path → 切换到Libraries标签页:
- 确认所有FreeTTS相关jar(freetts.jar、cmu_us_kal.jar等)均在Classpath下,而非Modulepath下
- 若误放到Modulepath,直接拖动到Classpath即可,保存后重试运行
2. 临时解决方案:添加JVM参数开放受限包
(最快验证问题的方式,无需修改项目结构)
- 右键运行类
TextSpecchClass→Run As→Run Configurations - 切换到
Arguments标签页,在VM arguments输入框中添加以下参数:--add-exports java.base/com.sun.speech.freetts=ALL-UNNAMED --add-exports java.base/com.sun.speech.freetts.en.us.cmu_us_kal=ALL-UNNAMED - 点击
Apply→Run,验证是否正常运行
参数说明:这两条指令是告诉JDK核心模块
java.base,将FreeTTS的两个关键包开放给未命名模块(即传统类路径项目),绕过第三方包命名限制。
3. 长期固化方案
方案A:将项目转为模块化项目
- 在项目根目录新建
module-info.java,内容示例:module com.your.project { requires freetts; // 对应freetts.jar的自动模块名(jar文件名去掉.jar) requires jsapi; // 对应jsapi.jar的自动模块名 // 其余依赖jar的自动模块名按需添加 } - 回到Build Path的
Libraries标签页,将所有FreeTTS相关jar移动到Modulepath下 - 保存后运行,此时FreeTTS的jar会被识别为正式模块,不再受命名限制
方案B:修改FreeTTS的包名(彻底解决)
使用反编译工具+编译工具,将FreeTTS所有类的包名从com.sun.speech.freetts.*修改为非受限包名(如org.freetts.*),同时修改你的代码import语句即可。
内容的提问来源于stack exchange,提问作者Liron C
相关产品推荐
相关产品推荐

