What Everybody Should Know About Installing And Using Java On Ubuntu

JavaInstalling and switching between versions of Java on Ubuntu is a relatively simple process (with a couple of caveats), you just need to know the right commands. Considering that there was a time when I didn’t know this either I thought I’d share what I know (shouldn’t take long :)).

Anyways, first thing first. When we talk about installing Java on Ubuntu we are of course talking about Sun Java. You can also install Open JDK if you want, but most people will use the Sun version for their Java development. Of course these days there are several versions of Sun Java that are in mainstream use; well basically 2, Java1.5 and Java6 (I am sure things will be even more interesting when Java 7 comes out). Regardless of which version of the JDK you want to install the process to do this on Ubuntu is the same. You need to know what package you want to install and then you need to use our old friend apt-get.

Installing Java

In the case of the Sun JDK you will want to install either (or both) of:


The commands for this will be:

sudo apt-get install sun-java5-jdk


sudo apt-get install sun-java6-jdk

Once you put in your password apt-get will go ahead and do it’s thing. The only thing to watch out for is that with Java you might get a license screen popping up during the installation (i.e. it won’t just finish by itself, so don’t go away), you will need to accept. That’s it, you now have one or several version of Java installed.

Switching Between Versions

Of course, if you have more than one version installed it is probably for a reason and you will need to switch between them at some point. Ubuntu has a very handy command just for this, update-java-alternatives. Using this command is simple:

update-java-alternatives -l

Which will produce output similar to the following:

java-1.5.0-sun 53 /usr/lib/jvm/java-1.5.0-sun
java-6-sun 63 /usr/lib/jvm/java-6-sun

You can now pick one of the alternatives that were printed out and use the same command, with a different switch, to make Ubuntu use it as it’s default Java installation:

sudo update-java-alternatives -s java-6-sun

This will output a bunch of stuff:

Using '/usr/lib/jvm/java-6-sun/bin/appletviewer' to provide 'appletviewer'.
Using '/usr/lib/jvm/java-6-sun/bin/apt' to provide 'apt'.
Using '/usr/lib/jvm/java-6-sun/bin/extcheck' to provide 'extcheck'.
Using '/usr/lib/jvm/java-6-sun/bin/HtmlConverter' to provide 'HtmlConverter'.
Using '/usr/lib/jvm/java-6-sun/bin/idlj' to provide 'idlj'.
Using '/usr/lib/jvm/java-6-sun/bin/jarsigner' to provide 'jarsigner'.
Using '/usr/lib/jvm/java-6-sun/bin/jar' to provide 'jar'.
Using '/usr/lib/jvm/java-6-sun/bin/javac' to provide 'javac'.
Using '/usr/lib/jvm/java-6-sun/bin/javadoc' to provide 'javadoc'.
Using '/usr/lib/jvm/java-6-sun/bin/javah' to provide 'javah'.
Using '/usr/lib/jvm/java-6-sun/bin/javap' to provide 'javap'.
Using '/usr/lib/jvm/java-6-sun/bin/java-rmi.cgi' to provide 'java-rmi.cgi'.
Using '/usr/lib/jvm/java-6-sun/bin/jconsole' to provide 'jconsole'.
Using '/usr/lib/jvm/java-6-sun/bin/jdb' to provide 'jdb'.
Using '/usr/lib/jvm/java-6-sun/bin/jhat' to provide 'jhat'.
Using '/usr/lib/jvm/java-6-sun/bin/jinfo' to provide 'jinfo'.
Using '/usr/lib/jvm/java-6-sun/bin/jmap' to provide 'jmap'.
Using '/usr/lib/jvm/java-6-sun/bin/jps' to provide 'jps'.
Using '/usr/lib/jvm/java-6-sun/bin/jrunscript' to provide 'jrunscript'.
Using '/usr/lib/jvm/java-6-sun/bin/jsadebugd' to provide 'jsadebugd'.
Using '/usr/lib/jvm/java-6-sun/bin/jstack' to provide 'jstack'.
Using '/usr/lib/jvm/java-6-sun/bin/jstatd' to provide 'jstatd'.
Using '/usr/lib/jvm/java-6-sun/bin/jstat' to provide 'jstat'.
Using '/usr/lib/jvm/java-6-sun/bin/native2ascii' to provide 'native2ascii'.
Using '/usr/lib/jvm/java-6-sun/bin/rmic' to provide 'rmic'.
Using '/usr/lib/jvm/java-6-sun/bin/schemagen' to provide 'schemagen'.
Using '/usr/lib/jvm/java-6-sun/bin/serialver' to provide 'serialver'.
Using '/usr/lib/jvm/java-6-sun/bin/wsgen' to provide 'wsgen'.
Using '/usr/lib/jvm/java-6-sun/bin/wsimport' to provide 'wsimport'.
Using '/usr/lib/jvm/java-6-sun/bin/xjc' to provide 'xjc'.
Using '/usr/lib/jvm/java-6-sun/jre/bin/ControlPanel' to provide 'ControlPanel'.
Using '/usr/lib/jvm/java-6-sun/jre/bin/java' to provide 'java'.
Using '/usr/lib/jvm/java-6-sun/jre/bin/java_vm' to provide 'java_vm'.
Using '/usr/lib/jvm/java-6-sun/jre/bin/javaws' to provide 'javaws'.
Using '/usr/lib/jvm/java-6-sun/jre/bin/jcontrol' to provide 'jcontrol'.
Using '/usr/lib/jvm/java-6-sun/jre/lib/jexec' to provide 'jexec'.
Using '/usr/lib/jvm/java-6-sun/jre/bin/keytool' to provide 'keytool'.
Using '/usr/lib/jvm/java-6-sun/jre/bin/orbd' to provide 'orbd'.
Using '/usr/lib/jvm/java-6-sun/jre/bin/pack200' to provide 'pack200'.
Using '/usr/lib/jvm/java-6-sun/jre/bin/policytool' to provide 'policytool'.
Using '/usr/lib/jvm/java-6-sun/jre/bin/rmid' to provide 'rmid'.
Using '/usr/lib/jvm/java-6-sun/jre/bin/rmiregistry' to provide 'rmiregistry'.
Using '/usr/lib/jvm/java-6-sun/jre/bin/servertool' to provide 'servertool'.
Using '/usr/lib/jvm/java-6-sun/jre/bin/tnameserv' to provide 'tnameserv'.
Using '/usr/lib/jvm/java-6-sun/jre/bin/unpack200' to provide 'unpack200'.
Using '/usr/lib/jvm/java-6-sun/jre/lib/i386/libnpjp2.so' to provide
Using '/usr/lib/jvm/java-6-sun/jre/lib/i386/libnpjp2.so' to provide
Using '/usr/lib/jvm/java-6-sun/jre/lib/i386/libnpjp2.so' to provide
Using '/usr/lib/jvm/java-6-sun/jre/lib/i386/libnpjp2.so' to provide
Using '/usr/lib/jvm/java-6-sun/jre/lib/i386/libnpjp2.so' to provide
Using '/usr/lib/jvm/java-6-sun/jre/lib/i386/libnpjp2.so' to provide
Using '/usr/lib/jvm/java-6-sun/jre/lib/i386/libnpjp2.so' to provide

There are two things to note about the command.

  1. It needs root privileges, so you will need to execute it with sudo
  2. The name of the java version you pass to the command is one of the things that was printed out when you ran update-java-alternatives –l (i.e. java-6-sun or java-1.5.0-sun)

This is all you need to do to have your whole Ubuntu installation use a different version of Java. That’s all great, but there is one big problem.

The Built-In FAIL And How To Fix It

Many Java applications written these days rely on the existence of the JAVA_HOME environment variable (they use this variable to know which Java they should execute with). Unfortunately none of the commands we ran above set the JAVA_HOME environment variable. Instead you will normally have to wait until the first time you execute a Java application which fails when it tries to find JAVA_HOME before you realize that you will need to set this yourself.

Even then things are not quite that simple. The update-java-alternatives command relies quite heavily on symlinks so it may take a while to even figure out where your current Java is installed. Once you do figure it out and set your JAVA_HOME environment variable, you have to remember to update it if you decide to switch java versions later (by using the update-java-alternatives command).

I will try to save you some pain and tell you where things live and then show you how I set my JAVA_HOME so that it is automatically (almost) updated when you switch Java versions. So, the first thing you would need to do to figure out where things live is to run the following command:

which java

Which tells you that your java executable lives in:


Of course if you go and have a look you will see that it is actually a symlink to:


That in turn is also a symlink to something like (depending on your java version):


We’re almost there but not quite. You need to go back a few directories from the path above, more specifically you need to go to:


This is where all the JVMs that are on your system will be found, you will also notice that java-6-sun in this directory is actually a symlink to the java-6-sun- (your actual version may differ) directory. The story for java-1.5.0-sun is similar. So, now you know that if you’re currently using Java 6 then your JAVA_HOME path should be:


To make sure this path persists between shutdowns, you will need to put it in your .bashrc file. But, as I mentioned you don’t want to just hard-code it as you would need to come and change it when you switch versions. So instead you can add the following line to the end of your .bashrc file:

export JAVA_HOME=`readlink -f \`which javac\` | awk -Fbin '{print $1}'`

What this does is automatically work out what your JAVA_HOME path should be (and sets it)  depending on what version of Java you’re currently using. It finds where your java interpreter lives and follows all the symlinks if there are any (and we know there are several). It then uses awk to extract the path before any bin folders which will be the path to your JAVA_HOME. The reason all of this works is because:

  • the java compiler javac will always be in the bin folder of your JDK as opposed to the bin folder of your JRE (like the java executable itself could be), so extracting the path before the bin folder using awk, gives is the path to what JAVA_HOME should be
  • using readlink –f, allows us to follow multiple levels of symlinks, which is handy in this case since that’s what we need to do to actually get the real path of where the javac compiler lives

The only thing to remember with this is that once it is in your .bashrc, every time you switch Java versions you will need to close the terminal and open a new one, or source your .bashrc again to make sure the JAVA_HOME path is updated. It is not a perfect solution but it is a decent one and it does the job. However if someone knows of a way to do this without having to start a new terminal or source your profile, do leave a comment and share your knowledge with everyone.

That’s all you need to know to install and work with Java on Ubuntu like a pro :).

Image by Refracted Moments

  • Korny

    Two things:
    First, there used to be a secondary Eclipse Fail – it used it’s own, separate, eclipse.ini file to find Java! And it used a strange system-specific heuristic to work out the ‘best’ one. They may have fixed this, but there’s a chance you have to also tell Eclipse which java to use…

    And second, I wrote a similar script for setting JAVA_HOME – three years ago :)
    http://ubuntuforums.org/showthread.php?p=1296484#post1296484 – it’s not a one-liner, but you could turn it into a one-liner pretty easily:
    export JAVA_HOME=$(dirname $(dirname $(readlink -f $(which javac) ) ) )
    Note you are better off using $() than back-ticks, as they nest nicely.
    – Korny

    • I never noticed that with Eclipse, gotta have a look to see if it is still an issue (surely they would have fixed it, I know I am an eternal optimist :)).

      I knew I couldn’t have been the only one who was annoyed by that JAVA_HOME issue :), thanks for sharing your script and for the back-ticks tip.

  • Couldn’t you just alias update-java-alternatives so that it also includes that one-liner?

    • Certainly I believe you could. But you would really get nothing out of it that the solution above does not already give you. You still need to crack open your .bashrc at least once and you still need to open a new terminal after you run the commend to make sure everything works properly.

  • Or you could use synaptic ;)

    • Does synaptic set JAVA_HOME for you? I tend more towards the command line tools when I use linux, that’s where the power lies after all. But that’s just a guideline, I am happy to use anything if there is a compelling enough reason.

  • Matt

    someone should write a wrapper around update-java-alternatives that does this automatically. run the wrapper, does the listing, numbering them, asks user for which number VM, selects it, exports the variable…

    of course, I don’t know enough shell scripting to do this! (I also don’t have a need to do it)

    • That is definitely an idea, although an even better way would be to fix update-java-alternatives in the first place so that it does it out of the box. I might just look into that although my C skills are a little rusty :).

  • Korny

    Really, update-java-alternatives is a bit broken. It sets a global system-wide default, permanently, in the default PATH of every new process. And if you have multiple JVMs installed, you probably want to be able to override this choice sometimes – otherwise you’d just uninstall the old JVM.
    What you really need is replacement ‘java’, ‘javac’ etc. scripts that look for JAVA_HOME / JDK_HOME, and then use whatever they point to; that way a user would just need to set environment variables instead of running root-level scripts. ISTR that Suse used to do this, but it’s been a very long time since I used Suse.

  • Pingback: Dew Drop – August 23, 2009 | Alvin Ashcraft's Morning Dew()

  • In reality, most developers I know who work with Ubuntu install the JDK directly from Sun, instead of using the version bundled with Ubuntu. Doing this makes setting JAVA_HOME a lot easier (no need to be jumping from symlink to symlink to find out the actual location of the JDK).

    Nevertheless this information is good to know, I was only vaguely familiar with the whole update alternatives thing. Nice writeup.

    • True it can be much easier to install Java directly rather than trying to play around with update-java-alternatives, which is a real shame cause it could work very well if it was fixed.

      I like the idea of being able to manage my Java installation through apt-get and it annoys me when I can do this with everything I install EXCEPT the JDK.

  • Howdy,

    I wrote on the same topic a while ago, but for the users who want to use their own version of the JDK:


    Peace and mash :)

    • Cheers for sharing that, it’s a great writeup and a good idea (I might do this myself).

      Definitely something to keep in mind considering the unpleasantness Ubuntu makes you deal with in this area.

  • Instead of following the symlink to usr/lib/jvm/java-6-sun- you could also just set the symlink (usr/lib/jvm/java-6-sun) as JAVA_HOME. Works just fine for me.

    I have a script in /etc/profile.d/ that sets the Java environment variables for all users, so individuals don’t need to edit their .bashrc.

    • Agreed, setting it to the symlink works just as well, I guess my thinking is that if you can follow all the symlinks, you might as well (it is probably more difficult not to do so, in an automated way).

      profile.d is definitely a good way of doing it if you have a multi-user system.

  • Epo Jemba

    Another way of doing should be

    1) setting permanently JAVA_HOME to something like /usr/lib/jvm/home
    2) then the update command with a patch or alias change the symlink the good way

    this way remove restart tricks, and is elegant :)


    • Yeah maybe that one would be something to try, I might give it a go and see if it would work better. Cheers for the idea.

  • Epo Jemba

    /usr/lib/jvm/home is of course a symlink to the right java directory..

  • As much as I love Linux and enjoy programming in Java, I’ve wasted too many frustrating hours dealing with these issues. Eventually I gave up and just went with a VM solution. Now most of my Java dev is in a Windows VM using Eclipse.
    That’s not to say it’s difficult to get Java setup in Linux alongside Eclipse. But once you start deviating from a simple setup, that’s where it can go downhill fast.

    • Hehe, I think going to windows as your dev environment might be taking things a little too far :).

  • Pingback: David Mach » Jak zprovoznit Javu na Ubuntu()