Complete Java Setup Guide on macOS (Apple Silicon M Chips), Copy and Run for Beginners
2/22/2026
I recently moved from Windows to an M4 MacBook Air. In the AI era, macOS gives a better vibe-coding experience. This guide records my full Java environment setup process, and every command is copy-and-run.
Why move from Windows to Mac?
In AI-assisted development, many engineers are shifting from “typing every line” to “directing AI to implement.” This workflow needs:
- Smooth terminal-first development
- Better support for AI tools like Claude Code and Cursor
- Higher consistency between local and server environments
After moving to Apple Silicon, common issues appeared quickly:
- Why does JDK 8 fail to install?
- Why does Maven report
illegal instruction? - Why are dependency downloads so slow?
- How do I manage multiple JDK versions for different projects?
The root cause is usually the same: architecture migration (x86_64 to arm64) plus platform migration (Windows to macOS).
The good news: with the right tooling, these issues are straightforward to solve.
Why Homebrew + SDKMAN?
Traditional setup pain points
Manual installer workflows still work on macOS, but they are not ideal:
- Manual
JAVA_HOMEandPATHmanagement - Error-prone version switching
- Hard-to-clean leftovers after uninstalling
Homebrew can install Java, but SDK-level version management is less flexible than SDKMAN for daily Java work.
SDKMAN strengths
SDKMAN is built for side-by-side SDK management:
- Install / switch / remove by command
- Keep JDK 8, 17, and 21 in parallel
- Pin versions per project
- Manage Maven, Gradle, Kotlin, Scala, and more
Recommended pattern:
- Homebrew for system package management
- SDKMAN for Java ecosystem toolchains
Step 1: Install Homebrew
Apple Silicon default Homebrew path is /opt/homebrew (Intel is /usr/local).
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
Add Homebrew to PATH:
echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> ~/.zprofile
eval "$(/opt/homebrew/bin/brew shellenv)"
Verify:
brew --version
Step 2: Install SDKMAN
curl -s "https://get.sdkman.io" | bash
source "$HOME/.sdkman/bin/sdkman-init.sh"
sdk version
If sdk version prints successfully, SDKMAN is ready.
Step 3: Install multiple JDK versions
List candidates:
sdk list java
Useful distributions:
tem(Eclipse Temurin): stable and common in productionzulu(Azul Zulu): better practical support for JDK 8 on Apple Silicongraalce: GraalVM community build
Install versions:
sdk install java 21.0.10-tem
sdk install java 17.0.18-tem
sdk install java 8.0.482-zulu
Set default JDK:
sdk default java 21.0.10-tem
Check current version:
sdk current java
java -version
Temporary switch for current shell:
sdk use java 8.0.482-zulu
Permanent switch:
sdk default java 17.0.18-tem
List installed JDKs:
ls -1 ~/.sdkman/candidates/java

Step 4: Install Maven
List Maven versions:
sdk list maven
Install stable 3.9.x:
sdk install maven 3.9.12
sdk default maven 3.9.12
Verify:
mvn -v

Step 5: Project-level auto switching with .sdkmanrc
Enable auto env:
sdk config
Change:
sdkman_auto_env=true
Create .sdkmanrc per project.
Legacy project (JDK 8):
cat > .sdkmanrc << 'EOF2'
java=8.0.482-zulu
maven=3.9.12
EOF2
Spring Boot 3 project (JDK 17):
cat > .sdkmanrc << 'EOF2'
java=17.0.18-tem
maven=3.9.12
EOF2
New project (JDK 21):
cat > .sdkmanrc << 'EOF2'
java=21.0.10-tem
maven=3.9.12
EOF2
Activate and verify:
sdk env
Step 6: Speed up Maven downloads (China mirror)
Create settings:
mkdir -p ~/.m2
nano ~/.m2/settings.xml
Use Aliyun mirror:
<settings>
<mirrors>
<mirror>
<id>aliyun</id>
<mirrorOf>central</mirrorOf>
<name>Aliyun Central</name>
<url>https://maven.aliyun.com/repository/central</url>
</mirror>
</mirrors>
</settings>
Verify mirror usage:
mvn -X clean compile
Check for output like:
Using mirror aliyun (https://maven.aliyun.com/repository/central) for central
Step 7: Optional local repository relocation
Edit ~/.m2/settings.xml and add:
<localRepository>/Users/gfish/dev/maven-repository</localRepository>
Full example:
<settings>
<localRepository>/Users/gfish/dev/maven-repository</localRepository>
<mirrors>
<mirror>
<id>aliyun</id>
<mirrorOf>central</mirrorOf>
<name>Aliyun Central</name>
<url>https://maven.aliyun.com/repository/central</url>
</mirror>
</mirrors>
</settings>
Create target folder:
mkdir -p /Users/gfish/dev/maven-repository
(Optional) migrate old cache:
mv ~/.m2/repository/* /Users/gfish/dev/maven-repository/
Verify configured local repo path:
mvn help:evaluate -Dexpression=settings.localRepository -q -DforceStdout
Step 8: Quick validation checklist
brew --version
sdk version
sdk current java
sdk current maven
java -version
mvn -v
ls -1 ~/.sdkman/candidates/java
ls -1 ~/.sdkman/candidates/maven
mvn -X clean compile | grep aliyun
mvn help:evaluate -Dexpression=settings.localRepository -q -DforceStdout
If all checks pass, your Java environment is ready.
Troubleshooting
JDK 8 install failure
Symptom: sdk install java 8.x.x-tem fails.
Fix: use Zulu on Apple Silicon.
sdk install java 8.0.482-zulu
Maven illegal instruction
Cause: old Maven version (for example 3.3.x) is incompatible with Apple Silicon.
Fix:
sdk install maven 3.9.12
Mirror still slow
Check:
- Mirror URL is
https://maven.aliyun.com/repository/central mirrorOfiscentral, not*mvn -Xlogs confirm Aliyun mirror is used
Too much manual JDK switching
Fix: enable sdkman_auto_env=true and use .sdkmanrc in each project.
Reference environment layout
~/
├── .sdkman/
│ └── candidates/
│ ├── java/
│ │ ├── 8.0.482-zulu
│ │ ├── 17.0.18-tem
│ │ ├── 21.0.10-tem
│ │ └── current -> 21.0.10-tem
│ └── maven/
│ ├── 3.9.12
│ └── current -> 3.9.12
├── .m2/
│ ├── settings.xml
│ └── repository/ (or custom path)
└── .zprofile (contains brew shellenv)
Project layout:
~/projects/my-spring-boot-app/
├── .sdkmanrc
├── pom.xml
└── src/
Why macOS is strong for vibe coding
- Unix-first terminal workflow
- Better native experience for mainstream AI coding tools
- Stronger parity between local and production environments
- Great remote development setup with iTerm2 + tmux
Summary
Spend 30 minutes once, save many hours later:
- Fast and reliable JDK switching
- Project-level environment isolation
- Faster dependency downloads
- Reproducible setup on any new machine

Further reading
- Claude Code docs: https://docs.anthropic.com/claude-code
- Vibe coding practice article: https://m.blog.csdn.net/jjhfen00/article/details/158045319
- Eclipse Temurin: https://adoptium.net/temurin/releases/
- Azul Zulu: https://www.azul.com/downloads/?package=jdk
- SDKMAN: https://sdkman.io/
- Aliyun Maven repo: https://maven.aliyun.com/mvn/view