Oracle's proprietary Java Development Kit takes a bit of effort to install because it's not available through Ubuntu's official package repositories, but in a commercial setting it's often the preferred JDK.
It's not the only JDK out there of course. In particular we often find OpenJDK, packaged for Linux under the name Iced Tea, installed on Ubuntu because it's a dependency of other packages that require Java. We don't have to uninstall OpenJDK. Instead we make the JDKs coexist peacefully through the use of Debians Alternatives system, as we shall see later in the post.
Before we download Oracle's proprietary JDK, let's find out if we got 32 or 64 bit?
$ uname -a Linux box 4.2.0-16-generic #19-Ubuntu SMP Thu Oct 8 15:35:06 UTC 2015x86_64 x86_64 x86_64 GNU/Linux
Now head over to Oracle's technet and grab the JDK for download. If it says x86_64 in the output of uname, then we are looking for a JDK marked x64 on the download page. Be sure to get the tar.gz version. At the time of writing the latest JDK available is jdk-8u74-linux-x64.tar.gz.
First thing to do after downloading the file is to extract the tar archive:
$ umask 002
$ cd ~/Downloads
/Downloads$ tar xvzf jdk-8u74-linux-x64.tar.gz
The umask 002 insures that all newly created files, such as the ones we extract from the archive, are stripped of write access by other users than owner and group. This will come in handy later.
The archive is extracted to a folder named jdk1.8.0_74. We will move it to /usr/local, which is where one would put software that is not installed through Ubuntu's package management and it's a shared location available to all users on the system. We set file owner and group to root. We are not actually going to use Java as root. The permissions that really matter, are the ones assigned to other users than owner and group. Because we already set a umask that strips write access from other users, when the archive was extracted, no one can mess up the installation folder.
/Downloads$ sudo mv jdk1.8.0_74/ /usr/local/ /Downloads$ cd /usr/local /usr/local$ sudo chown -R root:root jdk1.8.0_74/
Now create a symbolic link /usr/local/java that redirects to the real java installation folder. If we install other versions of java, then we can switch between them by changing the symbolic link /usr/local/java without changing scripts or environment variable that reference /usr/local/java.
/usr/local$ sudo ln -s /usr/local/jdk1.8.0_74/ /usr/local/java
Some Java apps such as Apache Maven and Apache Tomcat will find Java through the environment variable $JAVA_HOME, others such as a Eclipse will look for it on the $PATH.
Since we are installing Java in a location available to all users on the system, the JAVA_HOME environment variable too must be available to everyone. That means putting it in /etc/environment:
/usr/local$ sudo nano /etc/environment
Add this line to the end of the file:
Save the file ctl+o and close it ctl+x. Re-login to apply the environment.
The env command should now list JAVA_HOME in its output:
/usr/local$ env | grep JAVA_HOME JAVA_HOME=/usr/local/java
Now let's add java to the $PATH. This is more of a challenge because OpenJDK also wants to put its binaries on $PATH.
First let's check if we already have java on the $PATH:
/usr/local$ java -version
java version "1.7.0_95" OpenJDK Runtime Environment (IcedTea 2.6.4) (7u95-2.6.4-0ubuntu0.15.10.1) OpenJDK 64-Bit Server VM (build 24.95-b01, mixed mode)
It appears OpenJDK is already installed. Should it not be present on your system now, it could still appear any time you install other software that depends on Java. We have to make the JDKs coexist no matter the current or future constellation. Luckily OpenJDK already uses Debian's Alternatives system. Rather than adding Oracle's proprietary JDK directly to $PATH, we make it available through Debian Alternatives, but with a higher priority than OpenJDK. I separated the update-alternatives commands with semicolon, so you can simply paste the whole block into a terminal window:
sudo update-alternatives --install /usr/bin/java java /usr/local/java/bin/java 2000; sudo update-alternatives --install /usr/bin/javac javac /usr/local/java/bin/javac 2000; sudo update-alternatives --install /usr/bin/jar jar /usr/local/java/bin/jar 2000; sudo update-alternatives --install /usr/bin/jdb jdb /usr/local/java/bin/jdb 2000; sudo update-alternatives --install /usr/bin/jstack jstack /usr/local/java/bin/jstack 2000; sudo update-alternatives --install /usr/bin/wsgen wsgen /usr/local/java/bin/wsgen 2000; sudo update-alternatives --install /usr/bin/wsimport wsimport /usr/local/java/bin/wsimport 2000; sudo update-alternatives --install /usr/bin/schemagen schemagen /usr/local/java/bin/schemagen 2000; sudo update-alternatives --install /usr/bin/xjc xjc /usr/local/java/bin/xjc 2000; sudo update-alternatives --install /usr/bin/javadoc javadoc /usr/local/java/bin/javadoc 2000; sudo update-alternatives --install /usr/bin/jarsigner jarsigner /usr/local/java/bin/jarsigner 2000; sudo update-alternatives --install /usr/bin/javaws javaws /usr/local/java/bin/javaws 2000; sudo update-alternatives --install /usr/bin/javah javah /usr/local/java/bin/javah 2000; sudo update-alternatives --install /usr/bin/javap javap /usr/local/java/bin/javap 2000; sudo update-alternatives --install /usr/bin/jdeps jdeps /usr/local/java/bin/jdeps 2000; sudo update-alternatives --install /usr/bin/jmap jmap /usr/local/java/bin/jmap 2000; sudo update-alternatives --install /usr/bin/jmc jmc /usr/local/java/bin/jmc 2000; sudo update-alternatives --install /usr/bin/jvisualvm jvisualvm /usr/local/java/bin/jvisualvm 2000; sudo update-alternatives --install /usr/bin/keytool keytool /usr/local/java/bin/keytool 2000; sudo update-alternatives --install /usr/bin/policytool policytool /usr/local/java/bin/policytool 2000;
Test the java version available on $PATH again:
/usr/local$ java -version java version "1.8.0_74"
Java(TM) SE Runtime Environment (build 1.8.0_74-b02) Java HotSpot(TM) 64-Bit Server VM (build 25.74-b02, mixed mode)
The output confirms that we now have Oracles's proprietary Hotspot JVM and development tools on $PATH.