Guide to Installing Java JDK on Windows and Mac
Java remains the backbone of countless desktop tools, Android studios, and server frameworks. A clean JDK install unlocks that ecosystem on any personal machine.
Both Windows and macOS hide small gotchas that can turn a five-minute job into an afternoon of path errors. This walkthrough shows exactly where to click, what to type, and how to verify the result.
Understanding the JDK vs. JRE Divide
The JDK bundles the compiler, debugger, and mission-critical headers. The JRE only ships the runtime, leaving you unable to build fresh code.
Modern releases collapsed the JRE into the JDK folder, yet IDEs still ask for a distinct JDK entry. Pick the full kit once and avoid mysterious “missing compiler” dialogs later.
Some tutorials still link to the old JRE offline installer. Bookmark the JDK download page so you never grab the wrong payload by habit.
Checking Existing Java Installations
Open a terminal and run java -version. If the command prints a path under “/Library/Internet Plug-Ins” or “C:ProgramDataOracle”, you inherited an outdated consumer runtime.
macOS users may spot Java 6 legacy files left by Apple. Leave those in place; the new JDK sits in a separate /Library/Java/JavaVirtualMachines folder and will override the older binary automatically.
Windows PowerShell can echo every java.exe found in $env:PATH. Delete orphan copies in System32 to prevent shadow versioning after the upgrade.
Downloading the Right JDK Release
Oracle’s site now pushes a log-in wall; alternate distributors such as Microsoft Build of OpenJDK, Eclipse Temurin, and Amazon Corretto skip that friction. Any of these builds passes the Java TCK and runs identically for most workloads.
Pick the LTS line unless you crave preview features. LTS updates arrive quarterly and spare you from surprise syntax changes when an IDE plugin updates.
Windows users should grab the .msi for silent install switches. macOS users can choose .pkg or Homebrew; both drop the same binaries, but Homebrew adds automatic brew upgrade support.
Windows Installation Step-by-Step
Running the Graphical Installer
Launch the .msi as administrator so the installer can write to Program Files. Accept the default path; custom folders often break toolchain assumptions in Gradle and Maven wrappers.
The wizard offers a “Public JRE” checkbox. Uncheck it; the JDK already contains the runtime, and a second copy only confuses uninstall routines.
Let the wizard finish and do not reboot. Modern installers register the binaries immediately; a restart merely slows you down.
Setting JAVA_HOME and PATH
Open System Properties → Environment Variables. Add JAVA_HOME pointing to the root JDK folder, not the bin subdirectory.
Edit the system PATH and append %JAVA_HOME%bin. Use the variable form so future upgrades only require one path change.
Launch a new PowerShell window and run Get-Command java. The source path should now show the JDK folder, proving the variable is wired correctly.
Verifying the Compiler
Type javac -version. If the shell prints a matching release number, the compiler is on the path and ready for builds.
Create a tiny file Hello.java with a single main method. Compile and run it to confirm the entire chain from source to byte-code to runtime.
Any “javac is not recognized” error means PATH still points to an old JRE. Re-check variable order; Windows picks the first hit it finds.
macOS Installation Step-by-Step
Using the PKG Installer
Double-click the .pkg and follow the prompts. Gatekeeper may block unsigned binaries from smaller vendors; approve the security exception once and the warning disappears.
The script drops the JDK under /Library/Java/JavaVirtualMachines. Finder hides this folder, but Terminal can ls it once the install finishes.
No reboot is required. macOS dynamically notices new JVM folders and surfaces them to /usr/libexec/java_home instantly.
Homebrew One-Line Install
brew install openjdk@17 fetches the latest LTS. Homebrew places everything under /opt/homebrew/opt/openjdk on Apple Silicon and /usr/local/opt/openjdk on Intel.
Link the formula into the system with brew link openjdk@17 --force. The step adds executables to /opt/homebrew/bin, which is already ahead of Apple’s stub java wrapper.
Run brew info openjdk@17 to see the exact caveats. Copy the export snippet into ~/.zprofile so every new shell inherits the correct JAVA_HOME.
Configuring the Shell Environment
Add export JAVA_HOME=$(/usr/libexec/java_home -v17) to your profile. The utility queries all installed JVMs and returns the newest matching version.
Save the file, open a fresh Terminal, and run echo $JAVA_HOME. The path should end with Contents/Home, confirming the variable skips the nested bin folder.
Run which javac. If the output points inside the JDK bundle, both compile and runtime links are live.
Handling Multiple JDK Versions
Developers often need Java 8 for legacy servers and Java 17 for new micro-services. Use jenv on macOS or SDKMAN! on both platforms to switch without editing variables by hand.
jenv add /Library/Java/JavaVirtualMachines/jdk1.8.0_361.jdk/Contents/Home/ registers the old build. jenv global 17 flips the default, while jenv local 8 drops a .java-version file in a single project.
Windows users can create short PowerShell functions such as Use-Java8 that overwrite JAVA_HOME and refresh PATH. Store them in your $PROFILE for one-word switches.
IDE Integration Checks
IntelliJ IDEA auto-detects JDKs listed by java_home. Add each new SDK through Project Structure → SDKs rather than relying on the default project JDK.
Visual Studio Code with the Java Extension Pack reads JAVA_HOME first, then falls back to PATH. Misaligned variables trigger silent failures where code compiles in terminal but shows red squiggles in the editor.
Eclipse stores JDK references in eclipse.ini. Edit the -vm line to point at the libjvm.dylib or jvm.dll file, not the java launcher, to avoid startup crashes after upgrades.
Common Post-Install Errors
“Unable to locate a Java Runtime” when launching Maven usually means the tool is running inside a sandboxed terminal that inherited a stale PATH. Restart the terminal or reboot the IDE process.
macOS security prompts that reappear on every javac call indicate the binary lacks the quarantine attribute strip. Run xattr -d com.apple.quarantine /path/to/javac once to silence Gatekeeper.
Windows antivirus can lock fresh .dll files during the first compile, throwing “Access Denied” on tools.jar. Exclude the JDK folder from real-time scanning or wait for the initial indexing wave to finish.
Uninstalling or Rolling Back
On Windows, use Apps & Features to remove the JDK entry. Manual deletion leaves registry keys that confuse future installers, so let the uninstaller finish completely.
macOS requires a simple sudo rm -rf /Library/Java/JavaVirtualMachines/jdk-17.jdk. Homebrew users run brew uninstall openjdk@17 to clean symlinks and cellar data.
After removal, clear JAVA_HOME and restart any open IDE. Stale pointers can make applications silently fall back to a half-deleted copy, producing baffling “file not found” traces.
Keeping the JDK Updated
Oracle releases quarterly security patches; third-party builds follow within days. Enable automatic update checks in your control panel or watch the vendor RSS feed.
Homebrew users run brew upgrade openjdk and re-link. Windows users download the new .msi and install over the old path; the installer bumps the minor version without touching your environment variables.
Always test a staging project after an update. Patch releases rarely break code, but LTS jumps may deprecate internal APIs your dependencies rely on.