How to switch JDK version on Mac OS X

Apple decided to remove the Java Preferences application in a software update and afterwards in has been difficult to change the JDK version on Mac OS X. I especially noticed this after I installed the JDK 8 early access preview which makes some of the tips that you find on various blogs online useless. After a lot of googling I finally found a simple solution that I’d like to share.

What you do is to edit your ~/.bash_profile and add the following:

function setjdk() {
  if [ $# -ne 0 ]; then
   removeFromPath '/System/Library/Frameworks/JavaVM.framework/Home/bin'
   if [ -n "${JAVA_HOME+x}" ]; then
    removeFromPath $JAVA_HOME
   fi
   export JAVA_HOME=`/usr/libexec/java_home -v $@`
   export PATH=$JAVA_HOME/bin:$PATH
  fi
 }
 function removeFromPath() {
  export PATH=$(echo $PATH | sed -E -e "s;:$1;;" -e "s;$1:?;;")
 }
setjdk 1.7

What the script does is to first remove other JDK versions in the PATH so that they won’t interfere with our new JDK version. Then it makes some clever use of /usr/libexec/java_home which is a command that lists installed JDK versions. The -v argument tells java_home to return the path of the JDK with the supplied version, for example 1.7. We also update the PATH to point to the bin directory of the newly found JAVA_HOME directory. At the end we can simply execute the function using

setjdk 1.7

which selects the latest installed JDK version of the 1.7 branch. To select a specific version you can simply execute

setjdk 1.7.0_51

instead. Run /usr/libexec/java_home -h to get more details on how to choose versions.

That’s it! All credits should go to Neeme Praks and his answer on superuser.com.

This Post Has 63 Comments

  1. Nelson

    Thanx for the script. Worked well for me.

  2. Joaquín

    Thanks man!

    I was running something like export JAVA_HOME=`java_home -v 1.6`, but the scripts also takes care of the PATH so it’s definitively more convenient.

    For those which, like in my case, don’t have ~/.bash_profile, you can also add it like an script under /usr/local/bin

  3. Günter

    Many thanks!

    Works really great for Java up to version 1.8

  4. Magnus Rydin

    Thank you very much for yet another very elegant solution to an annoying problem!

  5. George

    Works well but borks on the removeFromPath function when your Path contains a folder that contains spaces, for example “/Applications/Flash Player Debugger.app”.

  6. venu

    Thank you so much!

  7. Richard

    Great. Works perfectly well and solve a really annoying issue :)

  8. Margaret

    Thank you thank you, this saved my butt! I can’t believe Apple removed feature to change it trivially though :(

  9. Jitendra Vyas

    I’m getting this message in terminal after adding you code to .bash_profile

    Unable to find any JVMs matching version “1.7”.

    1. Johan Haleby

      And you’re sure that you have Java 7 installed?

  10. Yakov Fain

    This works for applications, but not for applets. I need my Firefox to use Java 1.7 plugin, but after running your script FIrefox still has Java 1.8 plugin and so far I don’t know how to make it switch to Java 1.7.

    Thanks for the script anyway!

  11. John Van Der Loo

    Thanks for this! Most helpful in managing multiple JDK versions.

  12. Niklas Modin

    This should be added to .bash_profile as part of JDK installation.
    Or perhaps burnt into an EPROM on every new Mac sold.

    Anyways, thank you for making my day suck a lot less !

  13. Ragunath Jawahar

    Life saver!

  14. Tyler

    Super simple and straight forward! Thank you so much!

  15. Jeff

    Great! Well-explained and just what I was looking for.

  16. Nicolas U.

    Time saver ! Thanks for sharing this.

  17. Fabio Quimbay

    Thank you Johan, the script works perfectly !!

  18. Chris

    I refined the script just a little bit to be able to choose from the existing versions, which saves entering the java_home -V:

    function setjdk() {
    if [ $# -ne 0 ]; then
    switchjdk $@
    else
    echo “Choose from the following Java versions:”
    choosejdk
    echo “Please enter the correct full version number:”
    read jdkPick
    switchjdk $jdkPick
    fi
    }

    function switchjdk() {
    removeFromPath ‘/System/Library/Frameworks/JavaVM.framework/Home/bin’
    if [ -n “${JAVA_HOME+x}” ]; then
    removeFromPath $JAVA_HOME
    fi
    export JAVA_HOME=`/usr/libexec/java_home -v $@`
    export PATH=$JAVA_HOME/bin:$PATH
    }

    function choosejdk() {
    allVersions=$(/usr/libexec/java_home -V)
    }

    function removeFromPath() {
    export PATH=$(echo $PATH | sed -E -e “s;:$1;;” -e “s;$1:?;;”)
    }

  19. Sujesh Chirackkal

    Thanks for this. Really helpful

  20. Torben Pedersen

    Works – nice, thanks.

  21. Mike

    SO awesome! Thanks for reposting this.

  22. michael

    This will work as well, and is relatively robust assuming ‘tr’ and ‘sed’ behave nicely (uses bash):

    ver=1.7 # or 1.8
    JAVA_HOME=$(/usr/libexec/java_home -v $ver)
    # save just in case...
    OLD_PATH=$PATH
    # one-liner... this is using gnu sed (macports) but should be generic enough
    PATH=$(printf -- "${PATH}\n"  | tr ':' '\n' | sed "s,.*JavaVirtualMachines.*,${JAVA_HOME}/bin," | tr '\n' ':' | sed 's/:$//')
    
  23. Martin Kretz

    I think JEnv (http://www.jenv.be/) solves the problem nicely, with added bonus of customizing java version for each directory.

    1. Johan Haleby

      Thanks for the tip, seems very useful.

  24. Ajay Singh

    Thanks! Works like a charm.

  25. Paul

    This was AWESOME. Thanks!

  26. Jessica

    Thanks for this function, really useful !

    However, I have a question : I need 2 versions (jdk 1.8 for maven and 1.7 for jboss).
    To switch between my 2 servers, I have to add or remove your function. Is there a solution to do have something who recognize automatically which version I need ? To avoid editing each time the bash profile ?
    Thanks in advance !

  27. Elias

    Thank you tons!!!

  28. Trey

    I think that line 5 should be: “removeFromPath $JAVA_HOME/bin”; otherwise, it leaves behind a stray “/bin:” each time you use setjdk. Except for that, it works great! I only noticed it because I changed the PATH after the call to setjdk and that borked the directory that I’d added.

  29. Anton

    THANKS – great help!!!

  30. Mike N

    Thanks. I’m using it with latest version of 1.8.

  31. Krupa Singavarapu

    Great this script is working for me.

  32. Ranky

    Very nice. Thanks.

  33. Paul Hilliar

    Awesome, awesome, awesome and awesome. Thanks for a great script!

  34. Brett Tofel

    very nice

  35. Alain Moretti

    Just want to thank you for this very useful tip !
    Works great when switching between 7u60 and 8u40

  36. Sohil

    Rocking!!!

    Thank you buddy.

  37. Steve Coffman

    I noticed that the removeFromPath was leaving the trailing /bin in the PATH. I corrected it (and made it pass shellcheck linter).


    `
    #!/bin/bash

    #From http://blog.jayway.com/2014/01/15/how-to-switch-jdk-version-on-mac-os-x-maverick/
    function setjdk() {
    if [ $# -ne 0 ]; then
    removeFromPath '/System/Library/Frameworks/JavaVM.framework/Home/bin'
    #Bash expansion will be "x" if JAVA_HOME set, emptystring if unset
    #http://wiki.bash-hackers.org/syntax/pe#use_an_alternate_value
    if [ -n "${JAVA_HOME+x}" ]; then
    removeJavaFromPath "${JAVA_HOME}/bin"
    fi
    export JAVA_HOME=$(/usr/libexec/java_home -v "$@")
    export PATH=$JAVA_HOME/bin:$PATH
    fi
    }
    function removeJavaFromPath() {
    export PATH="$(echo "$PATH" | sed -E -e "s;:$1;;" -e "s;$1:?;;")"
    }
    `

  38. Torbjorn Martinsen

    There is a different answer in the SuperUser question you linked with more upvotes. I ended up going for that solution – perhaps consider updating your article if you also like that solution better as your article was the top hit on google for me :)

  39. Sreedish

    That was superb!!! thanks a lot for solving an annoying problem

  40. Tunde

    I’m getting this error when I ran the file:

    Babatundes-iMac:~ tfalade$ source ~/.bash_profile
    -bash: /Users/tfalade/.bash_profile: line 3: syntax error near unexpected token `then’
    -bash: /Users/tfalade/.bash_profile: line 3: `  if [ $# -ne 0 ]; then’

    Is there something that I’m doing wrong?

  41. Tunde

    I’m getting this error when I ran the function:
    Babatundes-iMac:~ tfalade$ source ~/.bash_profile
    -bash: /Users/tfalade/.bash_profile: line 3: syntax error near unexpected token `then’
    -bash: /Users/tfalade/.bash_profile: line 3: `  if[ $# -ne 0 ]; then’

    Please help

  42. Josef

    Awesome, works like a charm! I forgot about changing the PATH, I typically just jet JAVA_HOME, but that stopped working recently (in some cases), since there very symlinks like /usr/bin/java ->

  43. Kostas Karkaletsis

    Thanks for the script. Works as it is described!

  44. Lyndon

    Many thanks. Works a treat!!

  45. vito

    Thanks ! Work great !

  46. KaelLuo

    Thanks for this, it work for me.
    Just setjdk 1.7 should not include in script

  47. Ali BAKAN

    thnx a lot.

  48. Stan

    Working great in 2018 on Sierra!

Leave a Reply