Tech > MacOSXOpenJDK

Mac OS X and OpenJDK

OpenJDK

These notes relate to installing OpenJDK 8 on Mac OS X 10.11 (El Capitan). Unfortunately, the process of building OpenJDK on Mac OS X seems to rarely be straight-forward. Be prepared to debug the build process. Alternatively, see under 'See also' at the end of this document for links to binary downloads of the OpenJDK.

If you don't have Mercurial installed, it can be installed using macports with sudo port install mercurial.

Get the code as described in JDK 8 Update Releases page. It seems the jdk8u-dev is a better version to use as it has tags that seem to relate to releases. Browse other repository choices at http://hg.openjdk.java.net/jdk8u/

$ hg clone http://hg.openjdk.java.net/jdk8u/jdk8u-dev openjdk8u-dev

In the OpenJDK source folder, run the get_source.sh script:

$ bash get_source.sh

Optionally, select a tag to build from:

$ hg tags | grep jdk8u111
$ sh ./common/bin/hgforest.sh update jdk8u111-b14

View README-builds.html in the downloaded source. It describes which version of Xcode to install for the build.

Although the instructions state to use JDK 1.7 to perform the build, it worked successfully for me using a 1.8 JDK.

Download the relevant .dmg package from https://developer.apple.com/download/more/. In this example it is Xcode 4.5.2 with a release date of Nov 1, 2012.

Create a new directory to keep this version of Xcode separate from any others. E.g.

$ sudo mkdir /Applications/Xcode4.5.2
$ sudo chgrp wheel /Applications/Xcode4.5.2

Open the downloaded Xcode .dmg package and copy the Xcode.app folder to the /Applications/Xcode4.5.2 folder using finder, so that it resides at /Applications/Xcode4.5.2/Xcode.app.

Switch the current version of Xcode:

$ sudo xcode-select --switch /Applications/Xcode4.5.2/Xcode.app

Optionally, confirm the switch

$ xcode-select --print-path
/Applications/Xcode4.5.2/Xcode.app/Contents/Developer

Run Xcode through the launcher and when prompted to Install additional required components? select the Install option.

Optionally, install ccache to improve C++ compiler performance. E.g. with macports sudo port install ccache.

If the version of ccache is greater than 3.1.9, you may need to apply the following patch as the existing test fails with higher versions. However, using ccache results in segmentation faults during the build, so I had to disable it by passing --disable-ccache to configure.

Patch with, e.g.:

$ patch -p1 <~/tmp/build-performance-m4.patch

diff -r 07c7b5880ac3 common/autoconf/build-performance.m4
--- a/common/autoconf/build-performance.m4  Wed Sep 21 13:39:51 2016 -0700
+++ b/common/autoconf/build-performance.m4  Wed Jan 11 15:03:16 2017 +0000
@@ -199,7 +199,7 @@
   # Only use ccache if it is 3.1.4 or later, which supports
   # precompiled headers.
   AC_MSG_CHECKING([if ccache supports precompiled headers])
-    HAS_GOOD_CCACHE=`($CCACHE --version | head -n 1 | grep -E 3.1.@<:@456789@:>@) 2> /dev/null`
+    HAS_GOOD_CCACHE=`($CCACHE --version | head -n 1 | grep -E 3.\(@<:@2-9@:>@\|1.@<:@456789@:>@\)) 2> /dev/null`
   if test "x$HAS_GOOD_CCACHE" = x; then
     AC_MSG_RESULT([no, disabling ccache])
     CCACHE=
diff -r 07c7b5880ac3 common/autoconf/generated-configure.sh
--- a/common/autoconf/generated-configure.sh  Wed Sep 21 13:39:51 2016 -0700
+++ b/common/autoconf/generated-configure.sh  Wed Jan 11 15:03:16 2017 +0000
@@ -3672,7 +3672,7 @@


 #
-# Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -3880,7 +3880,7 @@
 #CUSTOM_AUTOCONF_INCLUDE

 # Do not change or remove the following line, it is needed for consistency checks:
-DATE_WHEN_GENERATED=1449096260
+DATE_WHEN_GENERATED=1484146859

 ###############################################################################
 #
@@ -36093,7 +36093,7 @@
   # precompiled headers.
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking if ccache supports precompiled headers" >&5
 $as_echo_n "checking if ccache supports precompiled headers... " >&6; }
-    HAS_GOOD_CCACHE=`($CCACHE --version | head -n 1 | grep -E 3.1.[456789]) 2> /dev/null`
+    HAS_GOOD_CCACHE=`($CCACHE --version | head -n 1 | grep -E 3.\([2-9]\|1.[456789]\)) 2> /dev/null`
   if test "x$HAS_GOOD_CCACHE" = x; then
     { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, disabling ccache" >&5
 $as_echo "no, disabling ccache" >&6; }

Change to the project directory:

$ cd openjdk8u-dev

Then run configure:

$ bash configure

or include the path to Xcode if you haven't or don't wish to switch Xcode versions with xcode-select (as described above).

$ bash configure --with-xcode-path=/Applications/Xcode4.5.2/Xcode.app

or specify a specific "boot" JDK:

$ bash configure --with-xcode-path=/Applications/Xcode4.5.2/Xcode.app \
       --with-boot-jdk=/Library/Java/JavaVirtualMachines/jdk1.7.0_80.jdk/Contents/Home

and set the update version etc. appropriately, e.g. jdk8u111-b14

$ bash configure --with-update-version=111 --with-build-number=b14

There is a comment above the acceptable_simple_element function in ./openjdk8u-dev/jdk/src/share/bin/version_comp.c stating that Java Web Start may not consider a JRE as a match, depending on the version string. Something to consider if your Java Web Start applications won't run.

If configure fails, refer to the various options that can be passed to configure in README-builds.html.

Build:

$ make all

make help shows a list of targets. E.g. make bootcycle-images, which presumably ensures the built JDK is at least able to be used as a boot JDK to build itself and hopefully the next new version too.

If the build fails, use the following to show the shell commands being executed:

$ make LOG=trace JOBS=1 all

If you see the error couldn't understandkern.osversion during the build, export the following variable before building:

$ export MACOSX_DEPLOYMENT_TARGET=10.9

I found that make always hung on a dtrace command leaving the CPUs busy. Normally, there is more-or-less continual output from the build process, so if output stops, be suspicious the build has hung. You can further confirm it's hung by running du -s build periodically to see if there is anything being written to the build folder. If the disk usage stays static over a reasonable period of time (say a few minutes), it's undoubtedly hung.

I disabled dtrace with the following patch in the hotspot sub-project, e.g.:

$ cd hotspot
$ patch --dry-run -p1 <~/tmp/dtrace-make.patch
$ cd -

diff -r 05a6a5823aa5 make/bsd/makefiles/dtrace.make
--- a/make/bsd/makefiles/dtrace.make  Wed Sep 21 13:40:37 2016 -0700
+++ b/make/bsd/makefiles/dtrace.make  Wed Jan 11 11:20:13 2017 +0000
@@ -356,11 +356,11 @@
 #DTRACE_PROG=$(PATCH_DTRACE_PROG)
 #DTRACE_INCL=-I/opt/SUNWdtrd/include
 #else
-ifneq ("$(systemDtraceFound)", "")
-DTRACE_PROG=$(SYSTEM_DTRACE_PROG)
-else
+#ifneq ("$(systemDtraceFound)", "")
+#DTRACE_PROG=$(SYSTEM_DTRACE_PROG)
+#else

-endif # ifneq ("$(systemDtraceFound)", "")
+#endif # ifneq ("$(systemDtraceFound)", "")
 #endif # ifneq ("$(patchDtraceFound)", "")

 ifneq ("${DTRACE_PROG}", "")

If you see output similar to the following:

/usr/bin/make: invalid option -- '8'
/usr/bin/make: invalid option -- '/'
/usr/bin/make: invalid option -- 'a'
/usr/bin/make: invalid option -- '/'
/usr/bin/make: invalid option -- 'c'

The build script is trying to rewrite some -j arguments to a command line, but can rewrite paths which contain the letter j.

Applying the following patch in the hotspot sub-project should fix it, e.g.:

$ patch -p1 ~/tmp/adjust-mflags-sh.patch

diff -r 87ee5ee27509 make/bsd/makefiles/adjust-mflags.sh
--- a/make/bsd/makefiles/adjust-mflags.sh Tue Mar 04 11:51:03 2014 -0800
+++ b/make/bsd/makefiles/adjust-mflags.sh Tue Jan 10 18:13:58 2017 +0000
@@ -64,7 +64,7 @@
  echo "$MFLAGS" \
  | sed '
    s/^-/ -/
-   s/ -\([^  ][^   ]*\)j/ -\1 -j/
+   s/ -\([^  ][^   ]*\)-j/ -\1 -j/
    s/ -j[0-9][0-9]*/ -j/
    s/ -j\([^   ]\)/ -j -\1/
    s/ -j/ -j'${HOTSPOT_BUILD_JOBS:-${default_build_jobs}}'/
diff -r 87ee5ee27509 make/bsd/makefiles/gcc.make
--- a/make/bsd/makefiles/gcc.make Tue Mar 04 11:51:03 2014 -0800
+++ b/make/bsd/makefiles/gcc.make Tue Jan 10 18:13:58 2017 +0000
@@ -349,7 +349,7 @@
   # The macro takes the version with no dots, ex: 1070
   CFLAGS += -DMAC_OS_X_VERSION_MAX_ALLOWED=$(subst .,,$(MACOSX_VERSION_MIN)) \
       -mmacosx-version-min=$(MACOSX_VERSION_MIN)
-  LDFLAGS += -mmacosx-version-min=$(MACOSX_VERSION_MIN)
+  LFLAGS += -mmacosx-version-min=$(MACOSX_VERSION_MIN)
 endif

Images are built under ./build/macosx-x86_64-normal-server-release/images/ and can be symlinked from, or copied to, either ~/Libraray/Java/JavaVirtualMachines or /Libraray/Java/JavaVirtualMachines. E.g.

$ cd /Library/Java/JavaVirtualMachines
$ sudo ln -s /usr/local/src/openjdk8u-dev/build/macosx-x86_64-normal-server-release/images/j2sdk-bundle/jdk1.8.0_112.jdk

See Installing & Using the Mac OS X Port

The makefile's install target installs the binaries by default to /usr/local/. It can be changed with configure --prefix=/opt/local etc. Alternatively, instead of running the install target, copy the bundle image(s) to the /Library/Java/JavaVirtualMachines and use /usr/libexec/java_home (see man java_home). e.g.

$ export JAVA_HOME=`/usr/libexec/java_home '1.8+'`
$ java -version

or

$ /usr/libexec/java_home -exec java -version

Note that the install target creates objects under the build directory, even after a single make all. These end up with root ownership which is probably not desireable. Either running make all again, or make install as a non-root user first seems to avoid this conflict. Presumably there is a dependency ordering issue in the make scripts.

$ make install
$ sudo make install

The observed install process created a jvm folder under the specified prefix folder name, with the JDK home folder named after the version number within the jvm folder. Symlinks were created in the bin folder under the specified prefix soft-linking to the relevant binaries within the JDK home bin folder.

There doesn't appear to be an uninstall target, but the following should list all the broken symlinks after deleting the JDK home folder (under /usr/local/jvm).

$ find /usr/local/bin -type l -not -exec test -e '{}' \; -print

Obviously, after installing a new version, there shouldn't be any broken symlinks.

References:

Embedding JRE in a Mac app

See https://wiki.openjdk.java.net/display/MacOSXPort/How+to+embed+a+.jre+bundle+in+your+Mac+app

Uninstalling Oracle JRE/JDK on Mac

https://www.java.com/en/download/help/mac_uninstall_java.xml

Trouble-Shooting

java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty

E.g. if a standard JRE is installed, you could reference it's certificate file when executing java.

$ java -Djavax.net.ssl.trustStore=/Library/Internet\ Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/lib/security/cacerts -jar MY.jar

-- Frank Dean - 10 Jan 2017

See also:

Related Topics: InstallingMacPorts, MacOSXTips