MacOS自包含Java应用Info.plist中ClassPath配置失效求助
MacOS App Bundle中Java应用无法加载Jar内着色器资源的解决办法
问题描述
用jlink创建自包含Java应用并打包为MacOS App Bundle,修改Info.plist指定主类后应用可启动,但无法找到Jar内的着色器文件,报错提示找不到../../shader/texture01_xxx.vp。Jar存放于MakinaCraftApp.app/Contents/Resources/Java,尝试绝对ClassPath无效,怀疑权限或配置问题。
Info.plist内容
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>CFBundleExecutable</key> <string>bin/MakinaCraftApp</string> <key>CFBundleGetInfoString</key> <string>MachinaWJavaApp (1)1.0, Copyright {user} 2004. All rights reserved.</string> <key>CFBundleInfoDictionaryVersion</key> <string>6.0</string> <key>CFBundleIconFile</key> <string>MachinaWJavaApp (1).icns</string> <key>CFBundleIdentifier</key> <string>MakinaCraft</string> <key>CFBundleName</key> <string>MachinaWJavaApp2</string> <key>CFBundlePackageType</key> <string>APPL</string> <key>CFBundleSignature</key> <string>????</string> <key>CFBundleVersion</key> <string>1.0.1</string> <key>Java</key> <dict> <key>MainClass</key> <string>com.noatechnologies.machinawjava.MachinaWJavaApp</string> <key>StartOnMainThread</key> <true/> <key>Arguments</key> <array/> <key>ClassPath</key> <string>$JAVAROOT/gluegen_rt:$JAVAROOT/gluegen_rt_natives_macosx_universal:$JAVAROOT/jogl_all:$JAVAROOT/jogl_all_natives_macosx_universal:$JAVAROOT/jogamp_fat.jar</string> </dict> </dict> </plist>
报错堆栈
java.lang.Error: java.lang.RuntimeException: com.jogamp.opengl.GLException: No shader code found (source nor binary) for src: [../../shader/texture01_xxx.vp], bin: null at makinacraftmodule/com.noatechnologies.androidjavaapp.OpenGLAndroidApp.main(OpenGLAndroidApp.java:211) at makinacraftmodule/com.noatechnologies.machinawjava.MachinaWJavaApp.main(MachinaWJavaApp.java:203) at makinacraftmodule/com.noatechnologies.machinawjava.MachinaWJavaApp.main(MachinaWJavaApp.java:145) at makinacraftmodule/com.noatechnologies.machinawjava.MachinaWJavaApp.main(MachinaWJavaApp.java:111) Caused by: java.lang.RuntimeException: com.jogamp.opengl.GLException: No shader code found (source nor binary) for src: [../../shader/texture01_xxx.vp], bin: null at jogamp.fat/com.jogamp.common.util.awt.AWTEDTExecutor.invoke(AWTEDTExecutor.java:58) at jogamp.fat/jogamp.opengl.awt.AWTThreadingPlugin.invokeOnOpenGLThread(AWTThreadingPlugin.java:103) at jogamp.fat/jogamp.opengl.ThreadingImpl.invokeOnOpenGLThread(ThreadingImpl.java:201) at jogamp.fat/com.jogamp.opengl.Threading.invokeOnOpenGLThread(Threading.java:202) at jogamp.fat/com.jogamp.opengl.Threading.invoke(Threading.java:221) at jogamp.fat/com.jogamp.opengl.awt.GLCanvas.display(GLCanvas.java:503) at makinacraftmodule/com.noatechnologies.androidjavaapp.OpenGLAndroidApp.main(OpenGLAndroidApp.java:185) ... 3 more Caused by: com.jogamp.opengl.GLException: No shader code found (source nor binary) for src: [../../shader/texture01_xxx.vp], bin: null at jogamp.fat/com.jogamp.opengl.util.glsl.ShaderCode.create(ShaderCode.java:551) at jogamp.fat/com.jogamp.opengl.util.glsl.ShaderCode.create(ShaderCode.java:706) at jogamp.fat/com.jogamp.opengl.util.glsl.ShaderCode.create(ShaderCode.java:771) at jogamp.fat/jogamp.opengl.macosx.cgl.MacOSXCGLContext.createCALayerShader(MacOSXCGLContext.java:188) at jogamp.fat/jogamp.opengl.macosx.cgl.MacOSXCGLContext.access$4800(MacOSXCGLContext.java:84) at jogamp.fat/jogamp.opengl.macosx.cgl.MacOSXCGLContext$NSOpenGLImpl.associateDrawable(MacOSXCGLContext.java:946) at jogamp.fat/jogamp.opengl.macosx.cgl.MacOSXCGLContext.associateDrawable(MacOSXCGLContext.java:427) at jogamp.fat/jogamp.opengl.GLContextImpl.makeCurrent(GLContextImpl.java:740) at jogamp.fat/jogamp.opengl.GLContextImpl.makeCurrent(GLContextImpl.java:614) at jogamp.fat/jogamp.opengl.GLDrawableHelper.invokeGLImpl(GLDrawableHelper.java:1279) at jogamp.fat/jogamp.opengl.GLDrawableHelper.invokeGL(GLDrawableHelper.java:1147) at jogamp.fat/com.jogamp.opengl.awt.GLCanvas$12.run(GLCanvas.java:1442) at java.desktop/java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:308) at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:773) at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:720) at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:714) at java.base/java.security.AccessController.doPrivileged(AccessController.java:399) at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86) at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:742) at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:203) at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:124) at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:113) at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:109) at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101) at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:90)
解决步骤
1. 修正资源读取逻辑(核心问题)
代码中用了相对路径../../shader/texture01_xxx.vp,但MacOS App Bundle启动时工作目录是用户Home目录,且Jar内资源不能直接用文件系统路径访问,必须通过类加载器读取:
- 确保着色器文件已打包到Jar内的
shader/目录(比如在项目资源目录下创建shader,打包时自动加入Jar) - 用类加载器获取资源:
// 方式1:通过当前类的类加载器获取输入流 InputStream shaderStream = OpenGLAndroidApp.class.getResourceAsStream("/shader/texture01_xxx.vp"); // 方式2:通过上下文类加载器获取URL(适配JOGAMP的ShaderCode) URL shaderUrl = Thread.currentThread().getContextClassLoader().getResource("shader/texture01_xxx.vp"); ShaderCode.create(null, shaderUrl, null, ShaderType.VERTEX, null);
2. 完善Info.plist的ClassPath配置
当前ClassPath只包含JOGAMP相关Jar,缺少你自己的应用Jar,需要添加进去:
<key>ClassPath</key> <string>$JAVAROOT/你的应用.jar:$JAVAROOT/gluegen_rt:$JAVAROOT/gluegen_rt_natives_macosx_universal:$JAVAROOT/jogl_all:$JAVAROOT/jogl_all_natives_macosx_universal:$JAVAROOT/jogamp_fat.jar</string>
替换你的应用.jar为实际的Jar文件名,确保它在Contents/Resources/Java目录下。
3. 验证Jar内资源是否存在
用终端命令检查Jar内是否包含目标着色器文件:
jar tf 你的应用.jar | grep shader/texture01_xxx.vp
如果输出结果包含该路径,说明资源已正确打包;如果没有,检查打包配置,确保资源目录被包含。
4. 避免依赖工作目录的绝对路径
不要尝试用绝对路径指向App Bundle内的资源,因为不同用户的安装路径可能不同,且MacOS的沙箱机制可能限制文件访问,始终用类加载器读取Jar内资源是最可靠的方式。
内容的提问来源于stack exchange,提问作者Felipe
相关产品推荐
相关产品推荐

