如何为Homebrew打包Java GUI应用并解决NoClassDefFoundError报错
报错原因
com.apple.eawt.QuitHandler是苹果专属的旧版JDK私有API,仅在早期Oracle JDK for macOS版本中内置,Homebrew默认依赖的openjdk为标准开源实现,默认未导出该私有类。你本地直接运行java -jar正常,是因为你系统默认的JDK环境是包含该类的旧版Oracle JDK,和Homebrew使用的openjdk环境不一致。
该报错确实和你的程序是GUI应用相关:com.apple.eawt下的类都是专门用于适配macOS系统GUI交互特性的(比如系统菜单栏退出逻辑、停靠栏图标响应等),纯命令行Java应用不会调用该类,不会触发该报错。
解决方案
- 方案1:修改Homebrew安装脚本,给启动脚本添加JVM导出参数
把你安装脚本中的bin.write_jar_script行修改为如下内容,主动导出openjdk中隐藏的com.apple.eawt类:
该方案不需要修改应用源码,适配Java 9及以上版本的openjdk,优先推荐使用。bin.write_jar_script libexec/'FOSStriangulator.jar', 'fosstriangulator', :jvm_flags => ["--add-exports java.desktop/com.apple.eawt=ALL-UNNAMED"] - 方案2:替换应用中的私有API调用
如果你是应用的开发者,可以把所有com.apple.eawt相关的逻辑,替换为Java 9之后标准库提供的java.awt.Desktop接口中的对应方法,从根源上消除对私有API的依赖,适配所有标准JDK环境。 - 方案3:更换依赖的JDK版本
把配方中的依赖声明修改为depends_on "adoptopenjdk8",AdoptOpenJDK 8内置了com.apple.eawt相关类,无需修改代码即可正常运行,但JDK 8已经停止主流维护,仅作为临时兼容方案使用。
内容的提问来源于stack exchange,提问作者Tin Man
相关产品推荐
相关产品推荐

