上个月帮团队里两个新同事配Mac开发环境,一台M1芯片的MacBook Pro,一台Intel芯片的老款MacBook Air。本来想着JDK加Maven嘛,半小时搞定的事,结果愣是折腾了一个下午:一个卡在Homebrew下载报错,一个把JAVA_HOME写进了错误的配置文件,还有一个因为没配Maven镜像仓库,第一次构建等了近十分钟才把依赖拉下来。当时我就想把所有遇到过的问题一次性整理成一份能照着抄的文档。这篇文章就是那次的完整复盘,从JDK版本怎么选、Maven到底是干嘛的,到环境变量怎么配置、阿里云镜像仓库怎么加,再到各种常见报错怎么排查,一次性给你捋清楚。
1. 动手之前:先把JDK和Maven的版本关系摸清楚
1.1 为什么JDK版本会影响后续所有操作
很多刚接触Java开发的人会以为JDK就是个"装了就行"的东西,反正java -version能输出版本号就万事大吉。实际上JDK版本直接决定了你今天能不能编译项目、明天能不能部署上线。Java 8是过去十年的绝对主力,很多老项目的pom.xml里还写着source/target 1.8,你拿JDK 17去编,大概率会碰到一些老库不兼容的报错。反过来,新项目如果还在用Java 8,Spring Boot 3.x直接就拒绝运行,因为它要求JDK 17起步。
在Mac上装JDK,你首先得明确自己需要哪个版本。我一般会建议:维护老项目、面向上线系统稳定的,用JDK 8或者11;新项目、用Spring Boot 3或者打算试试虚拟线程的,优先JDK 17或者21。JDK 17是目前最主流的"新基线",它既是长期支持版本,又有不错的性能优化,绝大多数现代框架都能跑。JDK 21虽然已经发布很久了,但是很多公司的基础设施还没完全跟上,如果你不想当小白鼠,先装17是比较稳妥的选择。
另外,Mac从2020年开始全面转向Apple Silicon芯片,M1、M2、M3这三代芯片对JDK的需求和Intel芯片不完全一样。早期确实存在某些JDK版本在M1上有问题的情况,但是这两年Temurin、Zulu这些主流发行版都已经原生支持了,只要你下载对应的macOS AArch64(arm64)版本,基本不会遇到兼容性坑。
1.2 Maven是干嘛的,它和JDK怎么配合
第一次接触Maven的人都会问那句经典问题:Maven到底有什么用?简单说,项目的"依赖管理、构建流程、打包发布"这三件事,全归它管。你可以把Maven理解成一个工地包工头:你需要什么材料(依赖库),它帮你从仓库拉回来;材料缺什么补齐什么(依赖传递),它也一并处理好;什么时候砌墙什么时候封顶(编译、测试、打包、部署),全听它的生命周期指挥。
具体到技术层面,Maven最核心的机制是POM(Project Object Model),也就是项目根目录下那个pom.xml文件。你在这个文件里声明项目需要哪些依赖,比如spring-boot-starter-web、mybatis-plus、lombok,Maven就会根据坐标去中央仓库或者你配置的镜像仓库下载对应的jar包,然后放进本地仓库。本地仓库默认在~/.m2/repository目录下,所有项目共享。
Maven本身是Java程序,它运行的时候需要有JAVA_HOME环境变量,因为脚本要调用java命令去启动Maven进程。所以安装顺序必须是先装JDK、配好JAVA_HOME,再装Maven、配MAVEN_HOME。如果你先装了Maven再去配JDK,也没关系,只要JAVA_HOME最终指向正确即可,Maven启动时自己会去找。
1.3 安装方式选哪种:Homebrew还是官网手动解压
Mac上安装JDK和Maven无非三种方式:Homebrew包管理器、官网下载DMG安装包、手动解压tar.gz压缩包。这三条路我都走过,说下各自的感受。
| 安装方式 | 优点 | 缺点 | 适合人群 |
|---|---|---|---|
| Homebrew(brew install) | 命令简单、升级方便、Cask自动处理DMG挂载 | 依赖Homebrew本身,网络不稳时容易报错 | 已经装了Homebrew且熟悉它的人 |
| 官网DMG安装包 | 双键双击安装,图形化界面,路径稳定 | 下载需要访问官网,版本切换麻烦 | 新手、只装一个JDK的人 |
| 手动解压tar.gz | 完全可控,想放哪个目录放哪个目录,多版本管理方便 | 需要自己配置环境变量 | 想深度理解环境变量机制的人 |
我的个人推荐组合是:JDK用Homebrew Cask安装Temurin(Adoptium社区版),因为一条命令就能装完,还不容易把系统搞乱;Maven用官网手动解压,因为Maven的版本更新比较快,而且手动解压能让你直接看到bin目录下的mvn脚本,后续排查路径问题会直观很多。
不过要注意,如果你还没装Homebrew,我建议先别急着装,先把Homebrew装好,因为后面很多工具链(比如Git、Node、Redis)都可能通过它来装。Homebrew安装本身也有点小概率踩坑,我在第4章会单独讲。
2. JDK 17安装与JAVA_HOME环境变量配置
2.1 先确认Mac的芯片类型和系统版本
安装JDK前,先确认一件事:你的Mac是什么芯片。这一步很多人会忽略,导致下载了x86_64版本的JDK安装在ARM机器上,性能损失虽然不大,但有时候会出现诡异问题。打开终端,执行下面这条命令:
uname -m如果输出arm64,就是Apple Silicon芯片(M1/M2/M3);如果输出x86_64,就是Intel芯片。顺带可以看一眼系统版本:
sw_versmacOS 12及以上版本对JDK 17的支持都很完整。如果你的系统特别老,比如还在macOS 11以下,老老实实先升级系统,否则装新版JDK可能会遇到"无法验证开发者"之类的提示。
还有一点要提醒:新Mac默认终端是zsh,配置文件是~/.zshrc。网上很多教程还是教你改.bash_profile,那是针对老版本macOS的。如果你在.zshrc里配了环境变量,另一台是bash,那配置文件完全对不上。后面我会全部基于zsh来讲。
2.2 用Homebrew一条命令安装JDK
确认完芯片后,如果你的Mac已经装好了Homebrew,直接用下面这条命令安装Temurin 17:
brew install --cask temurin@17这里说明一下为什么推荐Temurin而不是Oracle JDK。Oracle JDK 17虽然也能用,但它的商业许可条款有各种限制,而且需要登录Oracle账号才能下载。Temurin是Eclipse Adoptium社区维护的开源JDK发行版,和Oracle JDK同源,绝大多数企业项目都在用它,完全免费,Homebrew的Cask仓库里直接就有。
安装完成之后,默认会装到/Library/Java/JavaVirtualMachines/temurin-17.jdk这个路径。我们可以查看一下:
/usr/libexec/java_home -V这条命令会列出系统里所有已安装的JDK版本和对应路径,是Mac上管理JDK的核心工具,后面还会反复用到。如果你不想用Homebrew,也可以去Temurin官网下载dmg安装包,双击安装,效果一样。
2.3 JAVA_HOME环境变量配置(最关键的步骤)
JDK装好了,但终端输入java -version时,macOS其实已经能识别了,因为系统自带的工具链里有指向默认JDK的符号链接。但要真正稳定使用,尤其是让Maven、Spring、IDEA等工具都能找到正确的JDK,必须配置JAVA_HOME环境变量。
用编辑器打开~/.zshrc文件:
open -e ~/.zshrc如果文件不存在会新建一个。然后把下面这段加进去:
export JAVA_HOME=$(/usr/libexec/java_home -v 17) export PATH=$JAVA_HOME/bin:$PATH保存后执行:
source ~/.zshrc这里重点解释一下第一行的写法。很多人习惯直接硬编码JDK路径,比如export JAVA_HOME=/Library/Java/JavaVirtualMachines/temurin-17.jdk/Contents/Home,这种写法不是说不能用,而是当系统里装了多个JDK、或者你升级了JDK之后,路径一变你就要手动改。而/usr/libexec/java_home -v 17这个命令是macOS自带的JDK定位工具,它会自动找到符合版本号的JDK并返回真实路径,版本切换时环境变量自动跟着变,非常省心。
配完后验证一下:
java -version javac -version echo $JAVA_HOME正常情况下,java和javac都输出17.x.x的版本号,JAVA_HOME指向temurin-17.jdk里的Contents/Home目录。
2.4 JDK多版本切换的实用技巧
实际开发中经常碰到这种情况:手头维护的老项目要求JDK 8,新项目要求JDK 17,你总不能在两个项目之间反复卸载重装。Mac上有很优雅的切换方式。
首先把多个JDK都装上,比如用brew装一个temurin@8:
brew install --cask temurin@8然后在~/.zshrc里,除了默认的JAVA_HOME,再加几个别名方便切换:
export JAVA_HOME=$(/usr/libexec/java_home -v 17) export PATH=$JAVA_HOME/bin:$PATH alias jdk8='export JAVA_HOME=$(/usr/libexec/java_home -v 1.8); export PATH=$JAVA_HOME/bin:$PATH; java -version' alias jdk17='export JAVA_HOME=$(/usr/libexec/java_home -v 17); export PATH=$JAVA_HOME/bin:$PATH; java -version' alias jdk21='export JAVA_HOME=$(/usr/libexec/java_home -v 21); export PATH=$JAVA_HOME/bin:$PATH; java -version'source之后,你在终端里敲jdk8,当前这个shell窗口的JAVA_HOME就切到Java 8了;再敲jdk17,又切回17。注意这种方式只对当前终端窗口生效,新开窗口会重新读取~/.zshrc并还原成默认版本。这个特性反而很适合项目隔离,每个终端窗口可以各用各的JDK。
3. Maven安装与阿里云镜像仓库配置
3.1 下载Maven并解压到指定目录
Maven本身不需要安装程序,它是绿色软件,解压就能用。去Maven官网下载bin.tar.gz包,我写这篇时稳定版本是3.9.9,你可以根据自己需要选择3.8.x或者3.9.x。下载完成后,建议解压到一个固定的、权限可控的目录。
我习惯放在用户目录下的tools文件夹里,这样不涉及系统目录的写权限问题。执行:
mkdir -p ~/tools tar -xzf ~/Downloads/apache-maven-3.9.9-bin.tar.gz -C ~/tools解压完成,确认目录结构:
ls ~/tools/apache-maven-3.9.9你会在里面看到bin、conf、lib、boot等子目录。bin目录下有两个关键脚本:mvn和mvn.cmd,前者是macOS/Linux用的Shell脚本,后者是Windows用的。conf目录下的settings.xml是Maven的全局配置文件,后面要重点改它。
这里有个新手特别容易犯的错:直接把压缩包在"访达"里双击解压,从下载目录直接使用。这种临时路径不仅容易误删,在终端里切换到下载目录还经常因为空格或中文路径出问题。老老实实放到一个专门目录,比如~/tools、/opt/local或者/usr/local,路径清爽,后续配置省心。
3.2 配置MAVEN_HOME和PATH
Maven解压好之后,继续编辑~/.zshrc,加入下面两行:
export MAVEN_HOME=/Users/你的用户名/tools/apache-maven-3.9.9 export PATH=$MAVEN_HOME/bin:$PATH注意把"你的用户名"替换成你Mac的实际用户名,也就是home目录的名称。如果你解压到了/usr/local,那MAVEN_HOME就是/usr/local/apache-maven-3.9.9。
保存后source:
source ~/.zshrc然后验证:
mvn -v正常会输出类似这样的信息:
Apache Maven 3.9.9 Maven home: /Users/xxx/tools/apache-maven-3.9.9 Java version: 17.0.10, vendor: Eclipse Adoptium, runtime: /Library/Java/JavaVirtualMachines/temurin-17.jdk/Contents/Home看到Java version那一行显示17,说明Maven已经能正确找到你的JAVA_HOME了。如果这一步显示的是其他版本,说明JAVA_HOME不是指向17,回到上一章检查。
3.3 settings.xml配置:本地仓库路径
Maven默认的本地仓库在~/.m2/repository。这个目录会积累我们下载过的所有依赖jar包,动辄几GB甚至几十GB。问题在于,很多人的Mac里系统盘空间紧张,又或者你用的是公司电脑,home目录本身在云端同步盘里,这种目录同步几万个jar包既慢又占空间。
所以我习惯在settings.xml里自定义本地仓库路径。Maven的配置分全局和用户两级:全局配置在$MAVEN_HOME/conf/settings.xml,影响所有用户;用户配置在~/.m2/settings.xml,只影响当前用户,优先级更高。
我们创建一个用户级配置文件:
mkdir -p ~/.m2 vim ~/.m2/settings.xml填入最基础的内容:
<?xml version="1.0" encoding="UTF-8"?> <settings xmlns="http://maven.apache.org/SETTINGS/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd"> <localRepository>/Users/你的用户名/Documents/maven-repo</localRepository> </settings>localRepository标签的值就是你指定的仓库路径,路径不存在Maven会自动创建。我会把它放在Documents目录下,这样万一需要转移或者备份,直接剪切整个文件夹就行。如果你不介意默认位置,这步也可以跳过,不影响Maven工作。
3.4 settings.xml配置:阿里云镜像仓库
依赖下载慢是新手必遇的坎。Maven默认从中央仓库(repo.maven.apache.org)拉取依赖,这个仓库服务器主要在海外,国内访问经常只有几十KB/s,第一次构建一个Spring Boot项目,光下载依赖就能让你怀疑人生。
解决办法是配置国内镜像仓库。阿里云Maven镜像在国内非常稳定,配置方法也很简单,还是在settings.xml里,加入mirror节点:
<mirrors> <mirror> <id>aliyunmaven</id> <mirrorOf>*</mirrorOf> <name>阿里云公共仓库</name> <url>https://maven.aliyun.com/repository/public</url> </mirror> </mirrors>mirrorOf配置成*,表示所有依赖请求都走这个镜像,包括中央仓库、spring仓库、jboss仓库等都会被拦截到阿里云。阿里云的public仓库聚合了central、jcenter、public几大类,绝大多数开源依赖都能在里面找到。
有些老教程会让你同时配多个mirror,比如google、spring、aliyun加起来好几个。实际上不用,一个阿里云public就够了,配置多个反而可能因为镜像同步延迟导致某些特殊构件找不到。如果你在用一些冷门的私有仓库或者自建仓库,可以把mirrorOf写细一点,比如central, spring-milestones,否则自建仓库的请求也会被镜像劫持,这是常见的坑。
3.5 验证Maven是否安装成功
配置全部完成之后,我们拿一个实际项目来验证。不需要完整项目,建一个最简单的目录测试就行:
mkdir -p ~/test-maven && cd ~/test-maven创建一个简单的pom.xml:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.example</groupId> <artifactId>test-maven</artifactId> <version>1.0-SNAPSHOT</version> <properties> <maven.compiler.source>17</maven.compiler.source> <maven.compiler.target>17</maven.compiler.target> </properties> <dependencies> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.14.0</version> </dependency> </dependencies> </project>保存后执行:
mvn compile如果一切正常,你会发现commons-lang3的jar包很快就下载完成,构建输出BUILD SUCCESS。此时检查一下本地仓库路径:
ls ~/Documents/maven-repo/org/apache/commons/commons-lang3/3.14.0/能看到jar包存在,说明镜像配置和本地仓库配置都生效了。如果你看到下载进度一直在卡住,大概率是镜像配置没生效或者写错了,跳去第4章排查。
4. Mac安装JDK和Maven的常见报错排查
4.1 mac安装homebrew报错怎么处理
Homebrew的安装脚本默认从GitHub下载,国内网络环境下经常出现安装中途失败、443报错、curl连接超时这类问题。我见过最典型的一个报错是:
curl: (7) Failed to connect to raw.githubusercontent.com port 443: Connection refused解决思路其实很直接。第一,多试几次,网络波动时偶然失败很常见,重跑安装命令有时就好了。第二,确认你的网络环境本身是通的,浏览器能正常打开网页再试。第三,如果反复失败,可以使用国内高校或云厂商提供的Homebrew安装加速脚本,这类镜像本质上是把安装脚本和后续下载仓库的地址换成国内可访问的地址,属于常规的软件源优化,不改变Homebrew本身的行为。
安装完之后,如果你在brew install任何软件时都提示下载超时,也可以把Homebrew的默认下载源切换成国内镜像,具体操作官方文档都有,核心就是换git remote地址。注意换完源之后执行一遍brew update让仓库同步。
4.2 JAVA_HOME配置了但终端不认
这是配置环境变量最经典的报错,现象是:你明明在某个配置文件里写了export JAVA_HOME=xxx,也source了,但新开一个终端窗口就失效。原因九成是你把配置写错了文件。
macOS从Catalina开始默认shell是zsh,读取的配置文件顺序大致是:/etc/zprofile、~/.zprofile、~/.zshrc。如果你把环境变量写进.bash_profile或者.bashrc,终端启动时根本不会加载,只有手动执行source ~/.bash_profile才有用;如果你在旧项目的教程引导下改了/etc/paths文件,那又是另一种玩法,容易跟系统级配置混在一起。
正确做法就一句:统一把环境变量写进~/.zshrc,写完后source一次。如果这个文件不存在就新建。配置完以后,新开的终端窗口里echo $JAVA_HOME应该能正常输出版本路径。
还有个隐蔽情况:某些远程终端工具(比如你通过SSH或者自带配置的终端模拟器)启动时会加载不同的shell配置文件。排查时先执行echo $SHELL看看是不是zsh,再用type -a java看看命令到底是从哪里解析出来的。
4.3 java -version和javac -version版本对不上
这种问题比较隐蔽。java -version输出17,javac -version却输出1.8,明显是PATH里有多个JDK的bin目录在打架。常见的起因是:你之前在.bash_profile或者/etc/paths.d里配置过老JDK的路径,新配置的PATH追在后面,而系统解析命令时按PATH的先后顺序,遇到java就到处找,结果先找到了老的。
排查步骤很明确:
which -a java which -a javac几条结果都列出来之后,找到你是从哪个路径加载的。如果/usr/bin/java指向系统自带的符号链接,symlink最终指向哪里要看:
ls -l /usr/bin/java解决方法是调整~/.zshrc里PATH的拼接顺序,把$JAVA_HOME/bin放在最前面,也就是:
export PATH=$JAVA_HOME/bin:$PATH而不是:
export PATH=$PATH:$JAVA_HOME/bin两者的区别在于,前者优先使用你自己指定的JDK版本,后者是系统的PATH优先,就是个"先来后到"的问题。搞清楚这个逻辑,很多奇怪的版本错乱都能解释。
4.4 Maven下载依赖特别慢
如果你配好了阿里云镜像还是慢,先确认镜像到底有没有生效:
mvn help:effective-settings这条命令会输出当前生效的settings.xml内容。如果你能看到aliyunmaven这个mirror节点,说明用户级配置被正确加载了。如果看不到,可能原因有两个:一是settings.xml文件放错位置,二是IDEA里设置了独立的Maven配置覆盖了用户配置。
这里特别说一下IDEA的情况。IntelliJ IDEA默认会使用它内嵌的Maven,并且它读的是IDEA设置里指定的settings.xml路径,而不是~/.m2/settings.xml。你在IDEA的Preferences里搜索Maven,会看到Maven home path、User settings file、Local repository三个选项。如果你之前手动在IDEA里指定过其他settings.xml,那终端里配的阿里云镜像对IDEA完全无效。
我的建议是:让IDEA和终端共用同一套配置,也就是在IDEA的Maven设置里,把User settings file指到~/.m2/settings.xml,Local repository也指到同样的目录。这样两边行为一致,排查问题也简单。
4.5 终端一关再打开,命令又失效了
这个和4.2本质相同但表现不同:当前窗口source之后一切正常,关掉终端重新打开,mvn又提示command not found。问题就出在~/.zshrc没有被加载。
一种原因是你的终端配置里有其他脚本在启动时修改了PATH,比如某些终端美化工具、自定义.zprofile文件,导致~/.zshrc根本没被执行。排查方法:终端启动后直接执行grep -n zshrc ~/.zprofile,看看你装过的工具是否禁用了默认的zshrc加载。
另一个原因是Mac的"系统设置-用户与群组-登录项"里如果有终端环境管理工具(比如环境变量管理类的软件),它可能在启动时覆盖了你的PATH设置。这是很多增强型终端工具会干的事,不好排查,但可以通过在~/.zshrc的末尾强制追加PATH来解决,因为zshrc是最后执行的,优先级最高。
4.6 常见错误速查表
| 现象 | 可能原因 | 解决方案 |
|---|---|---|
| brew install报443 | 网络不稳定或下载源不可达 | 重试、换国内镜像源、检查网络 |
| java: command not found | 没装JDK或PATH里没加 | 先安装JDK再配置JAVA_HOME和PATH |
| JAVA_HOME为空 | 配置写入错误或不生效 | 检查~/.zshrc并source |
| mvn: command not found | Maven没解压或MAVEN_HOME没配 | 检查解压路径和PATH |
| mvn -v显示Java版本不对 | JAVA_HOME指向了其他版本 | 检查java_home -V和~/.zshrc |
| 依赖下载超时 | 镜像没生效或settings.xml错了 | 执行mvn help:effective-settings检查 |
| IDEA构建报错 | IDEA使用了内置Maven或不同settings.xml | 在IDEA Maven设置里指到~/.m2/settings.xml |
| 编译报source/target错误 | JDK版本和pom配置不匹配 | 调整JDK版本或pom里的compiler配置 |
5. 安装完成后的收尾配置:IDE和终端
5.1 在IDEA里把JDK和Maven指对
终端环境搞定了,不代表IDEA里就一切正常。IDEA默认会检测系统里的JDK,但有时候它会选到一个你没期望的版本。打开IntelliJ IDEA,进入File -> Project Structure -> Project,把SDK选成17,Language level也对应改成17。如果你需要同时维护多个项目,每个项目的SDK都可以单独设置,互不影响。
接着设置Maven。进入Preferences(macOS上是IntelliJ IDEA -> Settings) -> Build, Execution, Deployment -> Build Tools -> Maven,右边的Maven home path不要选Bundled,改成你解压的Maven目录,比如/Users/xxx/tools/apache-maven-3.9.9。User settings file选~/.m2/settings.xml,Local repository会自动跟着变成你设置的路径。
这里有个细节:改完Maven设置后,IDEA会重新导入项目,右下角会出现一个Maven导入进度条,如果依赖长时间卡住不动,去Local repository目录看看有没有jar包在生成,如果有就说明只是慢,等就好;如果什么都没有,检查IDEA里settings.xml的路径是否正确加载。
5.2 让终端更顺手的小技巧
环境装好之后,我习惯在~/.zshrc里加几个短命令,省得每次敲完整命令:
alias mvnc='mvn clean' alias mvncpackage='mvn clean package -DskipTests' alias mvncdep='mvn clean dependency:tree'然后再加一个自动清理Maven下载失败残留文件的命令,这个特别实用。依赖下载中断时,maven仓库里会留下很多.lastUpdated结尾的文件,导致之后重新下载一直失败。一条命令清掉:
alias mvncleanfailed='find ~/Documents/maven-repo -name "*.lastUpdated" -delete'执行完之后重新mvn compile,基本就能恢复正常下载。这个技巧是我在项目里踩了不少坑才总结出来的,比一个个去删文件高效太多。
还有一些人喜欢在终端显示当前JDK版本,可以改装一下提示符,但这属于锦上添花,不展开说。核心是把基础环境弄稳,工具用起来顺手,后面学习Java、写Spring项目、排查问题都能顺畅很多。
我自己的习惯是,每次配完新环境都会把java -version、javac -version、mvn -v三个命令各跑一遍,确认输出里Java版本一致、路径正确,再打开IDEA验证一次依赖导入。这套流程走完,基本可以保证一整天开发过程中不会再冒环境问题。如果你按这篇文章配置的过程中遇到其他奇怪报错,别急着百度,先确认三件事:JAVA_HOME对不对、PATH拼接顺序对不对、settings.xml有没有被正确加载。百分之八十的环境问题,都出在这三个环节上。