Installing Java 7 on Ubuntu Natty (11.04)

17 Aug 2011

It's been almost one month since the official release date (July 28th) of Java 7 and it is still not available in Ubuntu's software repository for Natty (11.04). There's one for Oneiric (11.10), sure, but cannot be installed into Natty.

I've seen some guides proposing how to install Java 7 on Natty, but all of them either do something wrong, or fail to explain what they are doing.

Here, I propose a way to install Java 7 (both OpenJDK and Sun) on Natty that won't make a mess on your system.

Java 7, OpenJDK

Last week Damien Lecan created a PPA with a backport of Oneiric's the .deb package and announced it in his blog. To install the JRE

$ sudo add-apt-repository ppa:dlecan/openjdk
$ sudo apt-get update
$ sudo apt-get install openjdk-7-jre

To install the JDK, replace the last line with sudo apt-get install openjdk-7-jdk.

Java 7 , Sun/Oracle

Some of you might prefer Sun/Oracle's JVM. Unfortunately, I've not found any PPA distributing it, therefore it has to be installed manually.

First of all, download the JDK from Oracle's download page to your home directory. You want jdk-7-linux-i586.tar.gz for 32-bit systems or jdk-7-linux-x64.tar.gz for 64-bit systems.

Then untar it with $ tar xf jdk-7-linux-x64.tar.gz.

The next step is to move the content of the tarball to the same directory where Ubuntu installs the JVMs, which is /usr/lib/jvm. You need sudo, because the destination directory is owned by root and has permissions 755: sudo mv ~/jdk1.7.0 /usr/lib/jvm/.

Now create a directory symlink called java-7-sun, pointing to jdk1.7.0, to follow Ubuntu's conventions: sudo ln -s /usr/lib/jvm/jdk1.7.0 /usr/lib/jvm/java-7-sun

We're almost there. Now you must configure Ubuntu's alternative system, by telling it about the new version you just downloaded. This is done by issuing a bunch of update-alternatives commands, telling the system the location of every new file.

The alternative system works by creating symlinks (mostly) in /usr/bin to /etc/alternatives, and then updating the links in /etc/alternatives to point to the actual executable. For example, in my system, /usr/bin/java points to /etc/alternatives/java, which in turn points to /usr/lib/jvm/java-7-sun/jre/bin/java. By issuing the command sudo update-alternatives --config java, Ubuntu prompts the user to select another alternative for /usr/bin/java, and simply updates the symlink /etc/alternatives/java to point to the newly selected provider.

I've studied the installation of Sun's Java 6 (packages sun-java6-bin, sun-java6-jdk and sun-java6-plugin), specifically the postinst scripts from each, merged and adapted the scripts, and produced a new one that would simply print into the screen the alternatives that have to be configured. Save the following content to a file (say, ~/java7config), then run it as root (sudo bash ~/java7config):

(Note: if you downloaded the 32-bit version, you should replace amd64 with i386! Thanks, satrapes!)

update-alternatives --quiet --install /usr/lib/xulrunner-addons/plugins/libjavaplugin.so xulrunner-1.9-javaplugin.so /usr/lib/jvm/java-7-sun/jre/lib/amd64/libnpjp2.so 63
update-alternatives --quiet --install /usr/lib/mozilla/plugins/libjavaplugin.so mozilla-javaplugin.so /usr/lib/jvm/java-7-sun/jre/lib/amd64/libnpjp2.so 63
update-alternatives --quiet --install /usr/bin/appletviewer appletviewer /usr/lib/jvm/java-7-sun/bin/appletviewer 63 --slave /usr/share/man/man1/appletviewer.1 appletviewer.1 /usr/lib/jvm/java-7-sun/man/man1/appletviewer.1
update-alternatives --quiet --install /usr/bin/apt apt /usr/lib/jvm/java-7-sun/bin/apt 63 --slave /usr/share/man/man1/apt.1 apt.1 /usr/lib/jvm/java-7-sun/man/man1/apt.1
update-alternatives --quiet --install /usr/bin/extcheck extcheck /usr/lib/jvm/java-7-sun/bin/extcheck 63 --slave /usr/share/man/man1/extcheck.1 extcheck.1 /usr/lib/jvm/java-7-sun/man/man1/extcheck.1
update-alternatives --quiet --install /usr/bin/idlj idlj /usr/lib/jvm/java-7-sun/bin/idlj 63 --slave /usr/share/man/man1/idlj.1 idlj.1 /usr/lib/jvm/java-7-sun/man/man1/idlj.1
update-alternatives --quiet --install /usr/bin/jar jar /usr/lib/jvm/java-7-sun/bin/jar 63 --slave /usr/share/man/man1/jar.1 jar.1 /usr/lib/jvm/java-7-sun/man/man1/jar.1
update-alternatives --quiet --install /usr/bin/jarsigner jarsigner /usr/lib/jvm/java-7-sun/bin/jarsigner 63 --slave /usr/share/man/man1/jarsigner.1 jarsigner.1 /usr/lib/jvm/java-7-sun/man/man1/jarsigner.1
update-alternatives --quiet --install /usr/bin/javac javac /usr/lib/jvm/java-7-sun/bin/javac 63 --slave /usr/share/man/man1/javac.1 javac.1 /usr/lib/jvm/java-7-sun/man/man1/javac.1
update-alternatives --quiet --install /usr/bin/javadoc javadoc /usr/lib/jvm/java-7-sun/bin/javadoc 63 --slave /usr/share/man/man1/javadoc.1 javadoc.1 /usr/lib/jvm/java-7-sun/man/man1/javadoc.1
update-alternatives --quiet --install /usr/bin/javah javah /usr/lib/jvm/java-7-sun/bin/javah 63 --slave /usr/share/man/man1/javah.1 javah.1 /usr/lib/jvm/java-7-sun/man/man1/javah.1
update-alternatives --quiet --install /usr/bin/javap javap /usr/lib/jvm/java-7-sun/bin/javap 63 --slave /usr/share/man/man1/javap.1 javap.1 /usr/lib/jvm/java-7-sun/man/man1/javap.1
update-alternatives --quiet --install /usr/bin/jconsole jconsole /usr/lib/jvm/java-7-sun/bin/jconsole 63 --slave /usr/share/man/man1/jconsole.1 jconsole.1 /usr/lib/jvm/java-7-sun/man/man1/jconsole.1
update-alternatives --quiet --install /usr/bin/jdb jdb /usr/lib/jvm/java-7-sun/bin/jdb 63 --slave /usr/share/man/man1/jdb.1 jdb.1 /usr/lib/jvm/java-7-sun/man/man1/jdb.1
update-alternatives --quiet --install /usr/bin/jhat jhat /usr/lib/jvm/java-7-sun/bin/jhat 63 --slave /usr/share/man/man1/jhat.1 jhat.1 /usr/lib/jvm/java-7-sun/man/man1/jhat.1
update-alternatives --quiet --install /usr/bin/jinfo jinfo /usr/lib/jvm/java-7-sun/bin/jinfo 63 --slave /usr/share/man/man1/jinfo.1 jinfo.1 /usr/lib/jvm/java-7-sun/man/man1/jinfo.1
update-alternatives --quiet --install /usr/bin/jmap jmap /usr/lib/jvm/java-7-sun/bin/jmap 63 --slave /usr/share/man/man1/jmap.1 jmap.1 /usr/lib/jvm/java-7-sun/man/man1/jmap.1
update-alternatives --quiet --install /usr/bin/jps jps /usr/lib/jvm/java-7-sun/bin/jps 63 --slave /usr/share/man/man1/jps.1 jps.1 /usr/lib/jvm/java-7-sun/man/man1/jps.1
update-alternatives --quiet --install /usr/bin/jrunscript jrunscript /usr/lib/jvm/java-7-sun/bin/jrunscript 63 --slave /usr/share/man/man1/jrunscript.1 jrunscript.1 /usr/lib/jvm/java-7-sun/man/man1/jrunscript.1
update-alternatives --quiet --install /usr/bin/jsadebugd jsadebugd /usr/lib/jvm/java-7-sun/bin/jsadebugd 63 --slave /usr/share/man/man1/jsadebugd.1 jsadebugd.1 /usr/lib/jvm/java-7-sun/man/man1/jsadebugd.1
update-alternatives --quiet --install /usr/bin/jstack jstack /usr/lib/jvm/java-7-sun/bin/jstack 63 --slave /usr/share/man/man1/jstack.1 jstack.1 /usr/lib/jvm/java-7-sun/man/man1/jstack.1
update-alternatives --quiet --install /usr/bin/jstat jstat /usr/lib/jvm/java-7-sun/bin/jstat 63 --slave /usr/share/man/man1/jstat.1 jstat.1 /usr/lib/jvm/java-7-sun/man/man1/jstat.1
update-alternatives --quiet --install /usr/bin/jstatd jstatd /usr/lib/jvm/java-7-sun/bin/jstatd 63 --slave /usr/share/man/man1/jstatd.1 jstatd.1 /usr/lib/jvm/java-7-sun/man/man1/jstatd.1
update-alternatives --quiet --install /usr/bin/native2ascii native2ascii /usr/lib/jvm/java-7-sun/bin/native2ascii 63 --slave /usr/share/man/man1/native2ascii.1 native2ascii.1 /usr/lib/jvm/java-7-sun/man/man1/native2ascii.1
update-alternatives --quiet --install /usr/bin/rmic rmic /usr/lib/jvm/java-7-sun/bin/rmic 63 --slave /usr/share/man/man1/rmic.1 rmic.1 /usr/lib/jvm/java-7-sun/man/man1/rmic.1
update-alternatives --quiet --install /usr/bin/schemagen schemagen /usr/lib/jvm/java-7-sun/bin/schemagen 63 --slave /usr/share/man/man1/schemagen.1 schemagen.1 /usr/lib/jvm/java-7-sun/man/man1/schemagen.1
update-alternatives --quiet --install /usr/bin/serialver serialver /usr/lib/jvm/java-7-sun/bin/serialver 63 --slave /usr/share/man/man1/serialver.1 serialver.1 /usr/lib/jvm/java-7-sun/man/man1/serialver.1
update-alternatives --quiet --install /usr/bin/wsgen wsgen /usr/lib/jvm/java-7-sun/bin/wsgen 63 --slave /usr/share/man/man1/wsgen.1 wsgen.1 /usr/lib/jvm/java-7-sun/man/man1/wsgen.1
update-alternatives --quiet --install /usr/bin/wsimport wsimport /usr/lib/jvm/java-7-sun/bin/wsimport 63 --slave /usr/share/man/man1/wsimport.1 wsimport.1 /usr/lib/jvm/java-7-sun/man/man1/wsimport.1
update-alternatives --quiet --install /usr/bin/xjc xjc /usr/lib/jvm/java-7-sun/bin/xjc 63 --slave /usr/share/man/man1/xjc.1 xjc.1 /usr/lib/jvm/java-7-sun/man/man1/xjc.1
update-alternatives --quiet --install /usr/bin/java-rmi.cgi java-rmi.cgi /usr/lib/jvm/java-7-sun/bin/java-rmi.cgi 63
update-alternatives --quiet --install /usr/bin/ControlPanel ControlPanel /usr/lib/jvm/java-7-sun/jre/bin/ControlPanel 63
update-alternatives --quiet --install /usr/bin/java java /usr/lib/jvm/java-7-sun/jre/bin/java 63
update-alternatives --quiet --install /usr/bin/java_vm java_vm /usr/lib/jvm/java-7-sun/jre/bin/java_vm 63
update-alternatives --quiet --install /usr/bin/javaws javaws /usr/lib/jvm/java-7-sun/jre/bin/javaws 63
update-alternatives --quiet --install /usr/bin/jcontrol jcontrol /usr/lib/jvm/java-7-sun/jre/bin/jcontrol 63
update-alternatives --quiet --install /usr/bin/keytool keytool /usr/lib/jvm/java-7-sun/jre/bin/keytool 63
update-alternatives --quiet --install /usr/bin/pack200 pack200 /usr/lib/jvm/java-7-sun/jre/bin/pack200 63
update-alternatives --quiet --install /usr/bin/policytool policytool /usr/lib/jvm/java-7-sun/jre/bin/policytool 63
update-alternatives --quiet --install /usr/bin/rmid rmid /usr/lib/jvm/java-7-sun/jre/bin/rmid 63
update-alternatives --quiet --install /usr/bin/rmiregistry rmiregistry /usr/lib/jvm/java-7-sun/jre/bin/rmiregistry 63
update-alternatives --quiet --install /usr/bin/unpack200 unpack200 /usr/lib/jvm/java-7-sun/jre/bin/unpack200 63
update-alternatives --quiet --install /usr/bin/orbd orbd /usr/lib/jvm/java-7-sun/jre/bin/orbd 63
update-alternatives --quiet --install /usr/bin/servertool servertool /usr/lib/jvm/java-7-sun/jre/bin/servertool 63
update-alternatives --quiet --install /usr/bin/tnameserv tnameserv /usr/lib/jvm/java-7-sun/jre/bin/tnameserv 63
update-alternatives --quiet --install /usr/bin/jexec jexec /usr/lib/jvm/java-7-sun/jre/lib/jexec 63

To conclude the installation, you must create (as root) the file /usr/lib/jvm/.java-7-sun.jinfo and add the following content:

(Note: if you downloaded the 32-bit version, you should replace amd64 with i386! Thanks, satrapes!)

name=java-7-sun
alias=java-7-sun
priority=63
section=non-free

jre ControlPanel /usr/lib/jvm/java-7-sun/jre/bin/ControlPanel
jre java /usr/lib/jvm/java-7-sun/jre/bin/java
jre java_vm /usr/lib/jvm/java-7-sun/jre/bin/java_vm
jre javaws /usr/lib/jvm/java-7-sun/jre/bin/javaws
jre jcontrol /usr/lib/jvm/java-7-sun/jre/bin/jcontrol
jre keytool /usr/lib/jvm/java-7-sun/jre/bin/keytool
jre pack200 /usr/lib/jvm/java-7-sun/jre/bin/pack200
jre policytool /usr/lib/jvm/java-7-sun/jre/bin/policytool
jre rmid /usr/lib/jvm/java-7-sun/jre/bin/rmid
jre rmiregistry /usr/lib/jvm/java-7-sun/jre/bin/rmiregistry
jre unpack200 /usr/lib/jvm/java-7-sun/jre/bin/unpack200
jre orbd /usr/lib/jvm/java-7-sun/jre/bin/orbd
jre servertool /usr/lib/jvm/java-7-sun/jre/bin/servertool
jre tnameserv /usr/lib/jvm/java-7-sun/jre/bin/tnameserv
jre jexec /usr/lib/jvm/java-7-sun/jre/lib/jexec
jdk appletviewer /usr/lib/jvm/java-7-sun/bin/appletviewer
jdk apt /usr/lib/jvm/java-7-sun/bin/apt
jdk extcheck /usr/lib/jvm/java-7-sun/bin/extcheck
jdk idlj /usr/lib/jvm/java-7-sun/bin/idlj
jdk jar /usr/lib/jvm/java-7-sun/bin/jar
jdk jarsigner /usr/lib/jvm/java-7-sun/bin/jarsigner
jdk java-rmi.cgi /usr/lib/jvm/java-7-sun/bin/java-rmi.cgi
jdk javac /usr/lib/jvm/java-7-sun/bin/javac
jdk javadoc /usr/lib/jvm/java-7-sun/bin/javadoc
jdk javah /usr/lib/jvm/java-7-sun/bin/javah
jdk javap /usr/lib/jvm/java-7-sun/bin/javap
jdk jconsole /usr/lib/jvm/java-7-sun/bin/jconsole
jdk jdb /usr/lib/jvm/java-7-sun/bin/jdb
jdk jhat /usr/lib/jvm/java-7-sun/bin/jhat
jdk jinfo /usr/lib/jvm/java-7-sun/bin/jinfo
jdk jmap /usr/lib/jvm/java-7-sun/bin/jmap
jdk jps /usr/lib/jvm/java-7-sun/bin/jps
jdk jrunscript /usr/lib/jvm/java-7-sun/bin/jrunscript
jdk jsadebugd /usr/lib/jvm/java-7-sun/bin/jsadebugd
jdk jstack /usr/lib/jvm/java-7-sun/bin/jstack
jdk jstat /usr/lib/jvm/java-7-sun/bin/jstat
jdk jstatd /usr/lib/jvm/java-7-sun/bin/jstatd
jdk native2ascii /usr/lib/jvm/java-7-sun/bin/native2ascii
jdk rmic /usr/lib/jvm/java-7-sun/bin/rmic
jdk schemagen /usr/lib/jvm/java-7-sun/bin/schemagen
jdk serialver /usr/lib/jvm/java-7-sun/bin/serialver
jdk wsgen /usr/lib/jvm/java-7-sun/bin/wsgen
jdk wsimport /usr/lib/jvm/java-7-sun/bin/wsimport
jdk xjc /usr/lib/jvm/java-7-sun/bin/xjc
plugin xulrunner-1.9-javaplugin.so /usr/lib/jvm/java-7-sun/jre/lib/amd64/libnpjp2.so
plugin mozilla-javaplugin.so /usr/lib/jvm/java-7-sun/jre/lib/amd64/libnpjp2.so

This file is read by update-java-alternatives, which in turn will call update-alternatives --config for each one of the executables listed above. So, to finish, update your symlinks:

sudo update-java-alternatives --set java-7-sun

Remember that some applications might read the environment variables JAVA_HOME or JDK_HOME, which you must update by yourself (by updating ~/.bash_rc, or ~/.bash_profile, or ~/.profile, or ~/.pam_environment, among many other alternatives).

Should you want to use another installed JVM, you can list the possibilities with:

sudo update-java-alternatives --list

That's all. The above procedure works on my machine. If you have any problems with it, don't panic, your system will probably not get broken. Leave a comment and we can try to fix it!

Note: if you have no update-java-alternatives, you can install it with sudo apt-get install java-common. Thanks, Leandro!

Good luck!