Introduction to OpenJDK
OpenJDK is an open-source
implementation of Oracle's Java Standard Edition platform.
OpenJDK is useful for developing
Java programs, and provides a
complete runtime environment to run Java programs.
This package is known to build and work properly using an LFS-7.7
platform.
Note
A browser plugin and webstart implementation, as well as a
pulseaudio sound backend are provided by the Icedtea project. To
provide a complete implementation, you will need to later install
IcedTea-Web-1.5.2 and IcedTea-Sound-1.0.1.
OpenJDK is GPL'd code, with a special exception made for non-free
projects to use these classes in their proprietary products. In
similar fashion to the LGPL, which allows non-free programs to link
to libraries provided by free software, the GNU General Public
License, version 2, with the Classpath Exception allows third
party programs to use classes provided by free software without the
requirement that the third party software also be free. As with the
LGPL, any modifications made to the free software portions of a
third party application, must also be made freely available.
Note
The OpenJDK source includes a
very thorough, open source test suite using the JTreg test harness. The testing instructions
below allow to test the just built JDK for reasonable
compatibility with the proprietary Oracle JDK. However, in order
for an independent implementation to claim compatibility, it must
pass a proprietary JCK/TCK test
suite. No claims of compatibility, even partial compatibility,
may be made without passing an approved test suite.
Oracle does provide free community access, on a case by case
basis, to a closed toolkit to ensure 100% compatibility with its
proprietary JDK. Neither the binary version provided on the
Java-1.8.0.31 page nor the JVM built with the
instructions below have been tested against the
TCK. Any version that is built using the instructions given,
cannot claim to be compatible with the proprietary JDK, without
the user applying for, and completing the compatibility tests
themselves.
With that in mind, the binaries produced using this build method
are regularly tested against the TCK by the members listed on the
site above. In addition to the community license above, an
educational, non-commercial license for the TCK can be obtained
from here.
Source Package Information
The following files may be downladed from the OpenJDK mercurial
repository using the addresses
http://hg.openjdk.java.net/jdk8u/jdk8u/<component>/archive/jdk8u31-b13.tar.bz2,
where <component> is the name of the JVM component (corba,
hostspot, and so on), but that involves renaming the downloaded
files, and renaming the extracted directories. For convenience, the
BLFS editors have made the files available in an LFS website.
Additional Downloads
OpenJDK Dependencies
Required Dependencies
An existing binary (Java-1.8.0.31 or an earlier built version of
this package), alsa-lib-1.0.28, cpio-2.11, Cups-2.0.2, UnZip-6.0, Which-2.20, Xorg Libraries, and
Zip-3.0
Recommended
Certificate Authority
Certificates and giflib-5.1.1
Optional
Mercurial-3.3 and twm-1.0.8 (for the tests)
User Notes: http://wiki.linuxfromscratch.org/blfs/wiki/openjdk
Installation of OpenJDK
Unlike other packages in BLFS, the OpenJDK source packages are distributed in
multiple tar balls. You need to first extract the source root from
jdk8u31-b13.tar.bz2
, change into the
extracted directory, then proceed with the following instructions:
tar -xf ../corba.tar.xz &&
tar -xf ../hotspot.tar.xz &&
tar -xf ../jaxp.tar.xz &&
tar -xf ../jaxws.tar.xz &&
tar -xf ../jdk.tar.xz &&
tar -xf ../langtools.tar.xz &&
tar -xf ../nashorn.tar.xz
If you have downloaded the test harness, unpack it too:
tar -xf ../jtreg4.1-b10.tar.gz
Fix an issue with the new (since 5.1.0) giflib API:
sed -e 's/DGifCloseFile(gif/&, NULL/' \
-e '/DGifOpen/s/c)/c, NULL)/' \
-i jdk/src/share/native/sun/awt/splashscreen/splashscreen_gif.c
Fix a bug in a shell script used to set the flags for make:
sed 's/\([ \t]\)\]\([^\]\)/\1I]\2/g' \
-i hotspot/make/linux/makefiles/adjust-mflags.sh
Note
Before proceeding, you should ensure that your environment
PATH
variable contains the location of
the Java compilers used for bootstrapping OpenJDK. This is the only requirement for
the environment. Modern Java installations do not need
JAVA_HOME
and CLASSPATH
is not used here. Furthermore, OpenJDK
developers recommand to unset JAVA_HOME
.
The build system does not support the -j
switch in MAKEFLAGS
.
Configure and build the package with the following commands
(--with-milestone value can be modified to fit user preferences):
unset JAVA_HOME &&
sh ./configure \
--with-update-version=31 \
--with-build-number=b13 \
--with-milestone=BLFS \
--enable-unlimited-crypto \
--with-zlib=system \
--with-giflib=system &&
make DEBUG_BINARIES=true all
It seems that the test infrastructure of OpenJDK is a work in
progress, so that testing the newly built JVM involves several
steps. First, it is better to run the test suite in a frame buffer
on a different display, using Xvfb:
if [ -n "$DISPLAY" ]; then
OLD_DISP=$DISPLAY
fi
export DISPLAY=:20
nohup Xvfb $DISPLAY \
-fbdir $(pwd) \
-pixdepths 8 16 24 32 > Xvfb.out 2>&1 &
echo $! > Xvfb.pid
echo Waiting for Xvfb to initialize; sleep 1
nohup twm -display $DISPLAY \
-f /dev/null > twm.out 2>&1 &
echo $! > twm.pid
echo Waiting for twm to initialize; sleep 1
xhost +
Then, it is necessary to modify some files:
echo -e "
jdk_all = :jdk_core \\
:jdk_svc \\
:jdk_beans \\
:jdk_imageio \\
:jdk_sound \\
:jdk_sctp \\
com/sun/awt \\
javax/accessibility \\
javax/print \\
sun/pisces \\
com/sun/java/swing" >> jdk/test/TEST.groups &&
sed -e 's/all:.*jck.*/all: jtreg/' \
-i langtools/test/Makefile
Some variables have to be set:
JT_JAVA=$(type -p javac | sed 's@/bin.*@@') &&
JT_HOME=$(pwd)/jtreg &&
PRODUCT_HOME=$(echo $(pwd)/build/*/images/j2sdk-image)
The tests are run as follows:
LANG=C make -k -C test \
JT_HOME=${JT_HOME} \
JT_JAVA=${JT_JAVA} \
PRODUCT_HOME=${PRODUCT_HOME} all
LANG=C ${JT_HOME}/linux/bin/jtreg -a -v:fail,error \
-dir:$(pwd)/hotspot/test \
-k:\!ignore \
-jdk:${PRODUCT_HOME} \
:jdk
The test results can be compared to these
results. Finally, stop the virtual frame buffer and clean up:
kill -9 `cat twm.pid` &&
kill -9 `cat Xvfb.pid` &&
rm -f Xvfb.out twm.out &&
rm -f Xvfb.pid twm.pid &&
if [ -n "$OLD_DISP" ]; then
DISPLAY=$OLD_DISP
fi
Install the package with the following commands as the root
user:
find build/*/images/j2sdk-image -iname \*.jar -exec chmod a+r {} \; &&
chmod a+r build/*/images/j2sdk-image/lib/ct.sym &&
find build/*/images/j2sdk-image -iname \*.diz -delete &&
find build/*/images/j2sdk-image -iname \*.debuginfo -delete &&
cp -R build/*/images/j2sdk-image /opt/OpenJDK-1.8.0.31 &&
chown -R root:root /opt/OpenJDK-1.8.0.31
There are now two OpenJDK SDKs
installed in /opt
. You should decide
on which one you would like to use as the default. Normally, you
would opt for the just installed OpenJDK. If so, do the following as the
root
user:
ln -v -nsf OpenJDK-1.8.0.31 /opt/jdk
If desired, you may install a .desktop file corresponding to an
entry in a desktop menu for policytool. First, you need to
obtain an icon from IcedTea-Web-1.5.2:
tar -xf ../icedtea-web-1.5.2.tar.gz \
icedtea-web-1.5.2/javaws.png \
--strip-components=1
Now, as root
user:
mkdir -pv /usr/share/applications &&
cat > /usr/share/applications/openjdk-8-policytool.desktop << "EOF" &&
[Desktop Entry]
Name=OpenJDK Java Policy Tool
Name[pt_BR]=OpenJDK Java - Ferramenta de Política
Comment=OpenJDK Java Policy Tool
Comment[pt_BR]=OpenJDK Java - Ferramenta de Política
Exec=/opt/jdk/bin/policytool
Terminal=false
Type=Application
Icon=javaws
Categories=Settings;
EOF
install -v -Dm0644 javaws.png /usr/share/pixmaps/javaws.png
The choice of pt_BR is just an example. You can add any translation
by adding lines corresponding to your locale, e.g. for fr_FR,
“Name[fr_FR]=” and
“Comment[fr_FR]=” with the
appropriate text as values.
Command Explanations
sh configure...: the
top level configure
is a wrapper
around the autotools one. It is not executable and must be run
through sh.
--with-boot-jdk
: This switch provides
the location of the temporary JDK.
It is normally not needed if java is found in the PATH
.
--with-update-version
:
Currently, the build system does not include the update number in
the version string. It has to be specified here.
--with-build-number
: Again,
the build system does not include the build number in the version
string. It has to be specified here too.
--with-milestone
: Used to
customize the version string.
--enable-unlimited-crypto
:
Because of limitations on the usage of cryptography in some
countries, there is the possibility to limit the size of encryption
keys and the use of some algorithms in a policy file. This switch
allows to ship a policy file with no restriction. It is the
responsability of the user to ensure proper adherence to the law.
--with-zlib=system,
--with-giflib=system
: Allows to use the system
libraries instead of the bundled ones.
--with-jobs=N
: Allows to set the number
of jobs for make
equal to N. The default is the result of a calculation involving
the available memory and the number of processors. Note that even
if you specify N=1, some parallelization may be used during the
build. The SBU given above are with parallel jobs disabled, on a
single processor, single core, virtual machine.
--with-cacerts-file=...
: Specifies
where to find a cacerts
file.
Otherwise, an empty one is created. You can get it from an earlier
version of the package, or using the script below to generate one.
make DEBUG_BINARIES=true
all: The build fails if DEBUG_BINARIES is not set
to true.
find ... -iname '*.jar' -exec chmod
a+r {} \; and following line: Fix permission in
some library files, in order to allow all users to access them.
find ... -iname '*.diz'
-delete: This command and the the next one remove
redundant files.
Configuring
OpenJDK
Configuration Information
Normally, the JAVA environment has been configured after
installing the binary version, and can be used with the just
built package as well. Review Configuring the JAVA
environment in case you want to modify something.
To test if the man pages are correctly installed, issue
source /etc/profile
and man java to
display the respective man page.
Install or update the
JRE Certificate Authority Certificates (cacerts) file
Use the following procedure to install the cacerts
or to generate a new one if Certificate Authority
Certificates have been updated. First, if it is not already
present, generate the mkcacerts script as the
root
user:
cat > /opt/jdk/bin/mkcacerts << "EOF"
#!/bin/sh
# Simple script to extract x509 certificates and create a JRE cacerts file.
function get_args()
{
if test -z "${1}" ; then
showhelp
exit 1
fi
while test -n "${1}" ; do
case "${1}" in
-f | --cafile)
check_arg $1 $2
CAFILE="${2}"
shift 2
;;
-d | --cadir)
check_arg $1 $2
CADIR="${2}"
shift 2
;;
-o | --outfile)
check_arg $1 $2
OUTFILE="${2}"
shift 2
;;
-k | --keytool)
check_arg $1 $2
KEYTOOL="${2}"
shift 2
;;
-s | --openssl)
check_arg $1 $2
OPENSSL="${2}"
shift 2
;;
-h | --help)
showhelp
exit 0
;;
*)
showhelp
exit 1
;;
esac
done
}
function check_arg()
{
echo "${2}" | grep -v "^-" > /dev/null
if [ -z "$?" -o ! -n "$2" ]; then
echo "Error: $1 requires a valid argument."
exit 1
fi
}
# The date binary is not reliable on 32bit systems for dates after 2038
function mydate()
{
local y=$( echo $1 | cut -d" " -f4 )
local M=$( echo $1 | cut -d" " -f1 )
local d=$( echo $1 | cut -d" " -f2 )
local m
if [ ${d} -lt 10 ]; then d="0${d}"; fi
case $M in
Jan) m="01";;
Feb) m="02";;
Mar) m="03";;
Apr) m="04";;
May) m="05";;
Jun) m="06";;
Jul) m="07";;
Aug) m="08";;
Sep) m="09";;
Oct) m="10";;
Nov) m="11";;
Dec) m="12";;
esac
certdate="${y}${m}${d}"
}
function showhelp()
{
echo "`basename ${0}` creates a valid cacerts file for use with IcedTea."
echo ""
echo " -f --cafile The path to a file containing PEM"
echo " formated CA certificates. May not be"
echo " used with -d/--cadir."
echo ""
echo " -d --cadir The path to a directory of PEM formatted"
echo " CA certificates. May not be used with"
echo " -f/--cafile."
echo ""
echo " -o --outfile The path to the output file."
echo ""
echo " -k --keytool The path to the java keytool utility."
echo ""
echo " -s --openssl The path to the openssl utility."
echo ""
echo " -h --help Show this help message and exit."
echo ""
echo ""
}
# Initialize empty variables so that the shell does not pollute the script
CAFILE=""
CADIR=""
OUTFILE=""
OPENSSL=""
KEYTOOL=""
certdate=""
date=""
today=$( date +%Y%m%d )
# Process command line arguments
get_args ${@}
# Handle common errors
if test "${CAFILE}x" == "x" -a "${CADIR}x" == "x" ; then
echo "ERROR! You must provide an x509 certificate store!"
echo "\'$(basename ${0}) --help\' for more info."
echo ""
exit 1
fi
if test "${CAFILE}x" != "x" -a "${CADIR}x" != "x" ; then
echo "ERROR! You cannot provide two x509 certificate stores!"
echo "\'$(basename ${0}) --help\' for more info."
echo ""
exit 1
fi
if test "${KEYTOOL}x" == "x" ; then
echo "ERROR! You must provide a valid keytool program!"
echo "\'$(basename ${0}) --help\' for more info."
echo ""
exit 1
fi
if test "${OPENSSL}x" == "x" ; then
echo "ERROR! You must provide a valid path to openssl!"
echo "\'$(basename ${0}) --help\' for more info."
echo ""
exit 1
fi
if test "${OUTFILE}x" == "x" ; then
echo "ERROR! You must provide a valid output file!"
echo "\'$(basename ${0}) --help\' for more info."
echo ""
exit 1
fi
# Get on with the work
# If using a CAFILE, split it into individual files in a temp directory
if test "${CAFILE}x" != "x" ; then
TEMPDIR=`mktemp -d`
CADIR="${TEMPDIR}"
# Get a list of staring lines for each cert
CERTLIST=`grep -n "^-----BEGIN" "${CAFILE}" | cut -d ":" -f 1`
# Get a list of ending lines for each cert
ENDCERTLIST=`grep -n "^-----END" "${CAFILE}" | cut -d ":" -f 1`
# Start a loop
for certbegin in `echo "${CERTLIST}"` ; do
for certend in `echo "${ENDCERTLIST}"` ; do
if test "${certend}" -gt "${certbegin}"; then
break
fi
done
sed -n "${certbegin},${certend}p" "${CAFILE}" > "${CADIR}/${certbegin}.pem"
keyhash=`${OPENSSL} x509 -noout -in "${CADIR}/${certbegin}.pem" -hash`
echo "Generated PEM file with hash: ${keyhash}."
done
fi
# Write the output file
for cert in `find "${CADIR}" -type f -name "*.pem" -o -name "*.crt"`
do
# Make sure the certificate date is valid...
date=$( ${OPENSSL} x509 -enddate -in "${cert}" -noout | sed 's/^notAfter=//' )
mydate "${date}"
if test "${certdate}" -lt "${today}" ; then
echo "${cert} expired on ${certdate}! Skipping..."
unset date certdate
continue
fi
unset date certdate
ls "${cert}"
tempfile=`mktemp`
certbegin=`grep -n "^-----BEGIN" "${cert}" | cut -d ":" -f 1`
certend=`grep -n "^-----END" "${cert}" | cut -d ":" -f 1`
sed -n "${certbegin},${certend}p" "${cert}" > "${tempfile}"
echo yes | env LC_ALL=C "${KEYTOOL}" -import \
-alias `basename "${cert}"` \
-keystore "${OUTFILE}" \
-storepass 'changeit' \
-file "${tempfile}"
rm "${tempfile}"
done
if test "${TEMPDIR}x" != "x" ; then
rm -rf "${TEMPDIR}"
fi
exit 0
EOF
chmod -c 0755 /opt/jdk/bin/mkcacerts
Note
Doing a very large copy/paste directly to a terminal may result
in a corrupted file. Copying to an editor may overcome this
issue.
If you need to generate a cacerts
file, and there is already one in /opt/jdk/jre/lib/security
, it is better to make
a backup. Then, you can create a new one, as the root
user:
/opt/jdk/bin/mkcacerts \
-d "/etc/ssl/certs/" \
-k "/opt/jdk/bin/keytool" \
-s "/usr/bin/openssl" \
-o "/opt/jdk/jre/lib/security/cacerts"
Use the following commands to check if the cacerts
file has been successfully installed:
cd /opt/jdk
bin/keytool -list -keystore jre/lib/security/cacerts
At the prompt "Enter keystore password:", press the "Enter" key
if there is no keystore password defined. If the cacerts
file was installed correctly, you will
see a list of the certificates with related information for each
one. If not, you need to reinstall them.