MacOS沙箱Java应用调用内嵌命令行工具触发Signal 4错误求助
检查mytool的架构适配
你用的是M1Pro(arm64)系统,但JDK是x64版本,mytool如果只编译为x64架构,在arm64环境下靠Rosetta转译运行,沙箱里容易出问题。得把mytool编译成universal二进制(同时支持x64和arm64),或者和JDK同架构。
验证架构:lipo -info /Applications/MyApp.app/Contents/app/mytool,如果不是universal,重新编译时加参数-arch x86_64 -arch arm64。统一沙箱权限配置
主应用的.entitlements文件必须包含com.apple.security.inherit,这样子进程mytool才能继承沙箱权限,不能只给mytool加。主应用的entitlements示例:<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>com.apple.security.app-sandbox</key> <true/> <key>com.apple.security.inherit</key> <true/> </dict> </plist>打包时用jpackage指定主应用的entitlements:
--mac-entitlements /path/to/main.entitlements,同时mytool的签名也要用同一个entitlements文件。修改进程调用的路径方式
别用绝对路径,改用相对路径或者从应用包内动态获取路径,避免沙箱路径限制:// 获取应用包内app目录的路径 String appContentsPath = System.getProperty("java.home").replace("/Contents/Home", "/Contents/app"); String toolPath = appContentsPath + "/mytool"; Process process = Runtime.getRuntime().exec(new String[]{toolPath, "argument"});换用arm64架构的JDK
放弃x64的OpenJDK,改用arm64版本(比如Azul Zulu的arm64 JDK),彻底避免Rosetta转译带来的沙箱兼容问题,这大概率能解决spawn helper的信号错误。重新签名整个应用包
打包完成后,对整个.app包做深度签名,确保所有嵌套二进制(包括mytool和JDK文件)都有正确的签名和权限:codesign --force --deep --sign "Developer ID Application: 你的开发者名称 (TeamID)" --entitlements /path/to/main.entitlements /Applications/MyApp.app验证签名状态:
codesign -dv --verbose=4 /Applications/MyApp.app,确认所有组件的签名有效,权限继承正确。
内容的提问来源于stack exchange,提问作者RadekJ

