以下为我的项目中关于引用JDK下tools.jar的pom.xml片段,在windows,Linux下都工作正常,最近换到MacOS 11(Big Sur)下工作,命令行执行编译没有问题,但在eclipse(最新版本eclipse-java-2021-03-R-macosx-cocoa-x86_64.dmg)发现它不正常了。
代码语言:javascript复制 <profiles>
<profile>
<id>default-javadoc-profile</id>
<activation>
<activeByDefault>true</activeByDefault>
<file>
<exists>${java.home}/../lib/tools.jar</exists>
</file>
</activation>
<properties>
<toolsjar>${java.home}/../lib/tools.jar</toolsjar>
</properties>
</profile>
</profiles>
直接的原因就是找不到{java.home}/lib/tools.jar定义的文件,显然是{java.home}有问题。eclipse下maven中
cat /Applications/Eclipse.app/Contents/Eclipse/eclipse.ini
如下图可以看到安装eclipse时默认使用的是JRE 11而不是JDK,JRE中没有tools.jar所以就报错喽
怎么解决呢?
Eclipse使用本地JDK(放弃)
修改/Applications/Eclipse.app/Contents/Eclipse/eclipse.ini
让eclipse使用我电脑上安装的JDK 8做JVM,如下修改-vm
参数的值
-vm /usr/bin
关于修改eclipse的JVM,参见 eclipse官方说明:
https://wiki.eclipse.org/Eclipse.ini
然而这个方法是有代价的,因为我用的eclipse要求JRE 11版本,所以不能使用本地的JDK 8做JVM。
使用JDK8的eclipse
重新安装使用JDK8的eclipse 旧版本是一个解决办法,但降低版本对于最新的macOS 11 Big Sur系统会不会有兼容性问题也不可知,但我觉得太麻烦,不到万不得已不会使用这个方案。
本地JDK升级到11
升级本地的JDK版本到11,然后使用上述方法修改eclipse.ini
也是可以的,但对于我并不合适,因为我的项目都是基于JDK 7或8的,突然因此被迫升级JDK版本后面有多少麻烦也不可知。
所以我反复权衡没有采用这两个办法。
使用${evn.JAVA_HOME}
代替${java.home}
既然 {java.home}不可使用,使用 {evn.JAVA_HOME}这个环境变量总是可以的。它是不受eclipse应用程序影响的。
于是我把pom.xml做了如下修改,增一个针对macOS的profile
代码语言:javascript复制 <profile>
<id>osx-javadoc-profile</id>
<activation>
<os>
<family>mac</family>
</os>
</activation>
<properties>
<toolsjar>${env.JAVA_HOME}/lib/tools.jar</toolsjar>
</properties>
</profile>
这次的问题是找不到${env.JAVA_HOME}
环境变量。
事实上我确实在.zprofile
中已经添加了JAVA_HOME
定义。按道理不应该呀。为什么?对于我这个macOS的手新来说太不可理解了。
macOS 10以后默认的脚本解释器是zsh,不再是bash,所以这里不是修改.bash_profile
在google上一通找,下面这两篇文章让我基本搞明白了原因:
《Setting environment variables on OS X》 《Setting environment variables in OS X for GUI applications》
macOS平台下对于像eclipse这样的非命令行的应用程序(GUI application),运行时是不会从.zprofile,.zshrc或.bash_profile,.bashrc
读取环境变量的。如果要为应用程序设置环境就需要通过launchctrl setenv key value
方式来完成。
以设置 JAVA_HOME
为例
launchctl setenv JAVA_HOME=$(/usr/libexec/java_home)
在/etc/launchd.conf 添加
setenv JAVA_HOME=$(/usr/libexec/java_home)
的方式在Mac OS X 10.10 and higher版本已经不再支持参见: 《HowTo: Set an Environment Variable in Mac OS X - /etc/launchd.conf》
launchctrl setenv key value
方式只是设置环境变量并不能持久化,电脑重启就失效了。如何写配置文件让它持久化呢?
如何持久化1:.zshenv
.zshenv
是ZSH的环境变量设置文件,非交互式应用程序每次启动都会读取,将JAVA_HOME
在这里设置,eclipse等应用程序就可以正确获取。
echo "launchctl setenv JAVA_HOME=$(/usr/libexec/java_home)" > ~/.zshenv
显然该方法只对当前用户有效
如何持久化2:launchd.plist
下面这篇文章介绍了如何基于launchd.plist设置应用程序的环境变量
《HowTo: Set an Environment Variable in Mac OS X - launchd.plist》
具体做法还以JAVA_HOME为例:
在/Library/LaunchDaemons
下创建setenv.JAVA_HOME.plist
文件(文件名字随便你定义,后缀要为.plist
)
# 需要管理员权限
sudo touch /Library/LaunchDaemons/setenv.JAVA_HOME.plist
修改setenv.JAVA_HOME.plist
文件内容为如下
<?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>Label</key>
<string>setenv.JAVA_HOME</string>
<key>ProgramArguments</key>
<array>
<string>/bin/launchctl</string>
<string>setenv</string>
<string>JAVA_HOME</string>
<!-- your JDK path -->
<string>/Library/Java/JavaVirtualMachines/jdk1.8.0_281.jdk/Contents/Home</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>ServiceIPC</key>
<false/>
</dict>
</plist>
保存文件后重启电脑,则一切正常。 此方法是在系统中增加了环境变量设置,对电脑上的所有用户有效。
参考资料
《Setting environment variables on OS X》
《Setting environment variables in OS X for GUI applications》
《-vm value: macOS Example》
《HowTo: Set an Environment Variable in Mac OS X - /etc/launchd.conf》
《HowTo: Set an Environment Variable in Mac OS X - launchd.plist》
《What should/shouldn’t go in .zshenv, .zshrc, .zlogin, .zprofile, .zlogout?》
《ZSH: .zprofile, .zshrc, .zlogin - What goes where?》