Package management is critical to maintaining a well tuned system. However, not all programs lend themselves well to packages. My opinion is that Java is one of these programs. The java-based packages, namely JDK, ant, tomcat, eclipse and others are better maintained using "alternative" methods.

Ubuntu also maintains a page dedicated to Java installation.

/etc/alternatives

alternatives - maintain symbolic links determining default commands

The alternatives package is a set of scripts that maintains symlinks to program binaries. For packages that are "drag-and-drop" in that they don’t rely on system libraries, the alternatives script is a great way to maintain these programs. I tend to store this class of programs under the /opt directory, using a symlink from a generic name to the specific program folder:

/opt/java -> /opt/jdk1.5.0_02

I setup this symlink first so that if I upgrade to a new version, I only have to update this symlink.

Any binary that needs to be available in the system path should get its own "alternative." An alternative is setup using the syntax:

alternatives --install link name path priority

To put some values to those placeholders, the following would be an example install of the alternative for java.

alternatives --install /usr/bin/java java /opt/java/bin/java 50

In order to enable automatic selection of the highest priority alternative, run the alternatives script again with the --auto flag.

alternatives --auto java

Note: The alternatives script is usually found in /usr/sbin, so be sure to that directory in your path when executing the above script. On debian systems, the alternatives script name is update-alternatives.

Consult this blog entry for updated instructions on how to install Sun’s Java on Ubuntu 8.10 (Intrepid).

Environment Variables

Now that the binaries point to the appropriate places, it is necessary to set the imfamous JAVA_HOME and perhaps some other java related environment variables. This is typically done by creating the script /etc/profile.d/java.sh so that it is sourced by the shell load scripts. An implementation of this script would look like:

# java initialization

export JAVA_HOME=/opt/java
export ANT_HOME=/opt/ant

export PATH=$PATH:$JAVA_HOME/bin:$ANT_HOME/bin

The paths are added so that it is possible to execute the other java-related binaries. If you setup alternatives for each of the binaries, there is no need to add them to your path.

SELinux Hangups

Recently, I have gotten into using remote debug for testing my java web applications. While doing some playing around at home, I discovered that if I started Eclipse under Java 1.4.2, the remote debug process would fail almost immediately (there was also some strange stuff going on with the console output from ant). After lots and lots of digging, I finally discovered that the issue is with socket binding in Java 1.4.2 under SELinux. A perfect explanation is described in a bug report filed with Red Hat’s bugzilla system. If you are using Java 5, you will not encounter this issue, since I guess the underlying problem was fixed. However, if you do have to use Java 1.4.2, there is a very simple workaround. Whichever processes kicks off java, just add the following vmarg: -Djava.net.preferIPv4Stack=true

Resources