Bookmark and Share

This is a note on my experience of installing Java on macOS 10.9.2.

macOS has its own system Java which as of macOS 10.9.2 is at version 1.6.0_65. It's more or less consistent with Java 6 (Java Language and Virtual Machine Specifications version SE 6). I'd like to keep macOS's system Java for various tasks and applications such as Mathematica which requires on Java 6. It's said that Apple no longer supports Java as a system component, so it's possile there will not be future major version update to Java 7 and higher.

The new "Java" I'd like to install is Oracle's Java. Oracle calls it "Java Platform (JDK) Platform". JDK is Java Development Kit which is the software package one needs to do Java software development. It's currently at version "Java SE 7" and is updated to "JDK SE 8" in March 2014. I'd like to install it for learning new Java features and used it in some projects.

macOS's system Java

The 'java' executable and Java Virtual Machines

The default command-line java on macOS 10.9.2 is version 1.6.0_65:

$ which java
/usr/bin/java
$ java -version
java version "1.6.0_65"
Java(TM) SE Runtime Environment (build 1.6.0_65-b14-462-11M4609)
Java HotSpot(TM) 64-Bit Server VM (build 20.65-b04-462, mixed mode)

This java along with other Java related binaries in the same path /usr/bin/ are actually symbolic links pointing to OS X's default installation directory for Java which in turn is part of system libraries /System/Library/:

$ ls -l /usr/bin/*java*
lrwxr-xr-x  1 root  wheel  74 Nov  3 10:29 /usr/bin/java -> /System/Library/Frameworks/JavaVM.framework/Versions/Current/Commands/java
lrwxr-xr-x  1 root  wheel  75 Nov  3 10:29 /usr/bin/javac -> /System/Library/Frameworks/JavaVM.framework/Versions/Current/Commands/javac
lrwxr-xr-x  1 root  wheel  77 Nov  3 10:29 /usr/bin/javadoc -> /System/Library/Frameworks/JavaVM.framework/Versions/Current/Commands/javadoc
lrwxr-xr-x  1 root  wheel  75 Nov  3 10:29 /usr/bin/javah -> /System/Library/Frameworks/JavaVM.framework/Versions/Current/Commands/javah
lrwxr-xr-x  1 root  wheel  75 Nov  3 10:29 /usr/bin/javap -> /System/Library/Frameworks/JavaVM.framework/Versions/Current/Commands/javap
lrwxr-xr-x  1 root  wheel  76 Nov  3 10:29 /usr/bin/javaws -> /System/Library/Frameworks/JavaVM.framework/Versions/Current/Commands/javaws

So the java at command line is actually using /System/Library/Frameworks/JavaVM.framework/Versions/Current/Commands/java. The Current directory is actually also a symbolic link:

$ ls -la /System/Library/Frameworks/JavaVM.framework/Versions/
total 64
drwxr-xr-x  11 root  wheel  374 Nov  3 10:30 .
drwxr-xr-x  12 root  wheel  408 Nov  3 10:30 ..
lrwxr-xr-x   1 root  wheel   10 Nov  3 10:29 1.4 -> CurrentJDK
lrwxr-xr-x   1 root  wheel   10 Nov  3 10:29 1.4.2 -> CurrentJDK
lrwxr-xr-x   1 root  wheel   10 Nov  3 10:29 1.5 -> CurrentJDK
lrwxr-xr-x   1 root  wheel   10 Nov  3 10:29 1.5.0 -> CurrentJDK
lrwxr-xr-x   1 root  wheel   10 Nov  3 10:29 1.6 -> CurrentJDK
lrwxr-xr-x   1 root  wheel   10 Nov  3 10:29 1.6.0 -> CurrentJDK
drwxr-xr-x   8 root  wheel  272 Nov  3 10:30 A
lrwxr-xr-x   1 root  wheel    1 Nov  3 10:29 Current -> A
lrwxr-xr-x   1 root  wheel   59 Nov  3 10:29 CurrentJDK -> /System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents

So this further mean the java at command line is actually using /System/Library/Frameworks/JavaVM.framework/Versions/A/Commands/java:

$ ls -la /System/Library/Frameworks/JavaVM.framework/Versions/A/Commands/java
-rwxr-xr-x  1 root  wheel  54624 Nov  3 10:29 /System/Library/Frameworks/JavaVM.framework/Versions/A/Commands/java
$ /System/Library/Frameworks/JavaVM.framework/Versions/A/Commands/java -version
java version "1.6.0_65"
Java(TM) SE Runtime Environment (build 1.6.0_65-b14-462-11M4609)
Java HotSpot(TM) 64-Bit Server VM (build 20.65-b04-462, mixed mode)

Difference between /System/Library/Frameworks/ and /Library/:

The /System/Library/Frameworks/ path is where macOS installs its essential framework packages such as Java. The framework packages are shared by multiple applications. Different applications may need different versions of the same package so in general there can be multiple versions of the same package. Third-party libraries is installed in /Library/.

/System/Library/Java/:

All the previous versions of Java {1.4, 1.5, ..., 1.6.0} is redirected to CurrentJDK and then to /System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents, perhaps for backwards compatibility. And the "current" Java is pointed to Current/ and then to A/. I guess 'A' stands for "Automatic". Also, I noted that there is one Apple's Java VM:

$ ls -la /System/Library/Java/JavaVirtualMachines/
total 0
drwxr-xr-x  3 root  wheel  102 Oct 10 11:13 .
drwxr-xr-x  5 root  wheel  170 Nov  3 10:30 ..
drwxr-xr-x  3 root  wheel  102 Oct 10 11:13 1.6.0.jdk

I'm not sure what's the relation between /System/Library/Frameworks/JavaVM.framework/ and /System/Library/Java. My guess is that JavaVM.framework is newly introduced and used 1) as an "interface" which maintain various links to /System/Library/Java/ for previous versions; 2) to store the "current" version of system "Java" in /System/Library/Frameworks/JavaVM.framework/Versions/A/.

Apple has a web site that provides downloading of macOS system Java.

JAVA_HOME environment variable

$ echo $JAVA_HOME
/System/Library/Frameworks/JavaVM.framework/Home
$ ls -la /System/Library/Frameworks/JavaVM.framework/Home
lrwxr-xr-x  1 root  wheel  24 Apr  1 19:36 /System/Library/Frameworks/JavaVM.framework/Home -> Versions/CurrentJDK/Home
$ ls -la /System/Library/Frameworks/JavaVM.framework/Versions/
total 64
drwxr-xr-x  11 root  wheel  374 Apr  1 19:37 .
drwxr-xr-x  12 root  wheel  408 Apr  1 19:37 ..
lrwxr-xr-x   1 root  wheel   10 Apr  1 19:36 1.4 -> CurrentJDK
lrwxr-xr-x   1 root  wheel   10 Apr  1 19:36 1.4.2 -> CurrentJDK
lrwxr-xr-x   1 root  wheel   10 Apr  1 19:36 1.5 -> CurrentJDK
lrwxr-xr-x   1 root  wheel   10 Apr  1 19:36 1.5.0 -> CurrentJDK
lrwxr-xr-x   1 root  wheel   10 Apr  1 19:36 1.6 -> CurrentJDK
lrwxr-xr-x   1 root  wheel   10 Apr  1 19:36 1.6.0 -> CurrentJDK
drwxr-xr-x   8 root  wheel  272 Apr  1 19:37 A
lrwxr-xr-x   1 root  wheel    1 Apr  1 19:36 Current -> A
lrwxr-xr-x   1 root  wheel   59 Apr  1 19:36 CurrentJDK -> /System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents 

Notice that it does not point to a Home inside /System/Library/Frameworks/JavaVM.framework/Versions/A/. Actually A/ does not contain a Home/. I'm not sure why there are both /System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Commands (which points to /System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home/bin/) and /System/Library/Frameworks/JavaVM.framework/Versions/A/Commands.

(Re-)install macOS's system Java

If for some reason you need to (re-)install Apple's system Java, you can download it from Apple's support site http://support.apple.com/downloads/#java. For example, as of April 2014, I will choose "Java for OS X 2013-005" for macOS 10.9.2.

There is also packages called "Java for macOS 10.6 Update 17 Developer Package" or "Java for OS X 2013-005 Developer Package" that "contains JavaDoc, tools documentation, and native framework headers". I've never tried these.

Preventing future macOS update to Java

If you decide to use Oracle JDK exclusively in future, it maybe desirable to more "thoroughly" delete Apple's Java. This is what I've not attempted to do.

The possible removals you'd need are

$ rm -rf /System/Library/Java/JavaVirtualMachines/
$ rm /private/var/db/receipts/com.apple.pkg.JavaForMacOSX*

and edit the installation receipts /Library/Receipts/InstallHistory.plist and remove the <dict> XML elements that has com.apple.Java* in it:

$ ack "com\.apple.*ava.*" /Library/Receipts/InstallHistory.plist
            <string>com.apple.pkg.JavaSDKLeo</string>
            <string>com.apple.pkg.JavaForMacOSX10.6Update3</string>
            <string>com.apple.pkg.JavaForMacOSX10.6Update4</string>
            <string>com.apple.pkg.JavaForMacOSX10.6Update5</string>
            <string>com.apple.pkg.JavaForMacOSX10.6</string>
            <string>com.apple.pkg.JavaForMacOSX10.6</string>
            <string>com.apple.pkg.JavaSecurity</string>
            <string>com.apple.pkg.JavaForMacOSX10.6</string>
            <string>com.apple.pkg.JavaSecurity</string>
            <string>com.apple.pkg.JavaForMacOSX10.6</string>
            <string>com.apple.pkg.JavaSecurity</string>
            <string>com.apple.pkg.JavaForMacOSX10.6</string>
            <string>com.apple.pkg.JavaSecurity</string>
            <string>com.apple.pkg.JavaForMacOSX10.6</string>
            <string>com.apple.pkg.JavaSecurity</string>
            <string>com.apple.pkg.JavaForMacOSX10.6</string>
            <string>com.apple.pkg.JavaSecurity</string>
            <string>com.apple.pkg.JavaForMacOSX10.6</string>
            <string>com.apple.pkg.JavaSecurity</string>
            <string>com.apple.pkg.JavaTools</string>
            <string>com.apple.pkg.JavaEssentials</string>
            <string>com.apple.pkg.JavaEssentials</string>
            <string>com.apple.pkg.JavaForMacOSX107</string>
            <string>com.apple.pkg.JavaSecurity</string>
            <string>com.apple.pkg.JavaMDNS</string>
            <string>com.apple.pkg.JavaEssentials</string>
            <string>com.apple.pkg.JavaForMacOSX107</string>
            <string>com.apple.pkg.JavaSecurity</string>
            <string>com.apple.pkg.JavaMDNS</string>
            <string>com.apple.pkg.JavaTools</string>
            <string>com.apple.pkg.JavaEssentials</string>
            <string>com.apple.pkg.JavaEssentials</string>
            <string>com.apple.pkg.JavaForMacOSX107</string>
            <string>com.apple.pkg.JavaSecurity</string>
            <string>com.apple.pkg.JavaMDNS</string>

Installing Oracle's Java

The path /Library/Java/

Third-party Java will be installed to /Library/Java. Note there is not a /System/ in front of it.

$ ls -la  /Library/Java
total 8
drwxrwxr-x   5 root  admin   170 Nov  3 10:30 .
drwxr-xr-x+ 72 root  wheel  2448 Mar  8 08:08 ..
drwxrwxr-x   2 root  admin    68 Nov  3 10:30 Extensions
lrwxr-xr-x   1 root  wheel    48 Nov  3 10:29 Home -> /System/Library/Frameworks/JavaVM.framework/Home
drwxr-xr-x   2 root  wheel    68 Nov  3 10:30 JavaVirtualMachines
$ ls -la /Library/Java/JavaVirtualMachines/
total 0
drwxr-xr-x  2 root  wheel   68 Nov  3 10:30 .
drwxrwxr-x  5 root  admin  170 Nov  3 10:30 ..

The symbolic link Home -> /System/Library/Frameworks/JavaVM.framework/Home is how macOS by default manages the $JAVA_HOME environment variable for third-party Java. $JAVA_HOME by default is set to /Library/Java/Home which is updated to point to the current version of Java /System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home/.

Currently I have no third-party Java and hence an empty /Library/Java/JavaVirtualMachines/.

To install a new non-system non-Apple Java on Mac, one can install Oracle's JDK, and possibly OpenJDK). These have versions newer than Apple's Java.

My goal at the time of writing this note is to install the newer Java (Java Language and Virtual Specification, version SE 7 or even version "Java SE 8") while keep macOS's own system Java (version "Java SE 6"), since I need both for different work.

Installing Oracle's JDK

To install "Java 7", download "Java SE Development Kit 7" for "macOS x64" from Oracle. Install that. After that, you should find /Library/Java/JavaVirtualMachines/ has the newly installed Oracle JDK:

$ ls /Library/Java/JavaVirtualMachines
jdk1.7.0_51.jdk
$ /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/bin/java -version
java version "1.7.0_51"
Java(TM) SE Runtime Environment (build 1.7.0_51-b13)
Java HotSpot(TM) 64-Bit Server VM (build 24.51-b03, mixed mode)

But this does not affect the default command-line java:

$ java -version
java 1.6.0_65

Now you have both Java 6 and 7 on the computer and can use them for different purposes.

Making Oracle Java binaries available at command line

Depending on if it's desirable to you, you may want to link Java related binaries in /usr/bin

$ ls -la /usr/bin/*java*
lrwxr-xr-x  1 root  wheel  74 Nov  3 10:29 /usr/bin/java -> /System/Library/Frameworks/JavaVM.framework/Versions/Current/Commands/java
lrwxr-xr-x  1 root  wheel  75 Nov  3 10:29 /usr/bin/javac -> /System/Library/Frameworks/JavaVM.framework/Versions/Current/Commands/javac
lrwxr-xr-x  1 root  wheel  77 Nov  3 10:29 /usr/bin/javadoc -> /System/Library/Frameworks/JavaVM.framework/Versions/Current/Commands/javadoc
lrwxr-xr-x  1 root  wheel  75 Nov  3 10:29 /usr/bin/javah -> /System/Library/Frameworks/JavaVM.framework/Versions/Current/Commands/javah
lrwxr-xr-x  1 root  wheel  75 Nov  3 10:29 /usr/bin/javap -> /System/Library/Frameworks/JavaVM.framework/Versions/Current/Commands/javap
lrwxr-xr-x  1 root  wheel  76 Nov  3 10:29 /usr/bin/javaws -> /System/Library/Frameworks/JavaVM.framework/Versions/Current/Commands/javaws

to Oracle's Java, either under a different name, say java7, or the default name java, and optionally rename the existing macOS's java to java6 first. I created java7:

$ sudo ln -s /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/bin/java /usr/bin/java7
$ sudo ln -s /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/bin/javac /usr/bin/javac7
...

And you probably want to keep $JAVA_HOME consistent with java. If java is pointing to Oracle Java, you'd want

$ ln -s /Library/Java/Home /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home

Managing JAVA_HOME for different environments

JAVA_HOME is a UNIX envrionment variable that are sometimes used to determine which and how Java Virtual Machine is run. It's a somewhat complex issue to set them appropriately for different purposes.

Here is what I've done:

Setting JAVA_HOME for Bash

Add the following code to shell configuration file. There are multiple configuration files for Bash shell including .profile, .bashrc, /etc/profile. For me, I used $HOME/.bashrc:

## Method 1: Set JAVA_HOME to macOS's system Java Home/ which is a symlink pointing to
## /System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home as of macOS 10.9.2
## When there are multiple versions of Java installed, using the /usr/libexec/java_home method below is better.
# export JAVA_HOME="/System/Library/Frameworks/JavaVM.framework/Home"

## Method 2: Alternatively, set the path using the /usr/libexec/java_home command with a parameter -v to choose specific version of Java
## Use the following to see verbose info about available versions of Java when unsure.
## /usr/libexec/java_home -V
## /usr/libexec/java_home -Vv 1.6

## Use Java 6    
export JAVA_HOME=`/usr/libexec/java_home -v 1.6`
## Use Java 7  
# export JAVA_HOME=`/usr/libexec/java_home -v 1.7`
## Use Java 8  
# export JAVA_HOME=`/usr/libexec/java_home -v 1.8`

So, potentially, one can tweak the lines in method 2 and choose different version to use. Notice that the binary /usr/libexec/java_home is used to determine the Java home directory:

$ /usr/libexec/java_home -V
Matching Java Virtual Machines (4):
    1.8.0, x86_64:  "Java SE 8" /Library/Java/JavaVirtualMachines/jdk1.8.0.jdk/Contents/Home
    1.7.0_51, x86_64:   "Java SE 7" /Library/Java/JavaVirtualMachines/jdk1.7.0_51/Contents/Home
    1.6.0_65-b14-462, x86_64:   "Java SE 6" /System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home
    1.6.0_65-b14-462, i386: "Java SE 6" /System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home

/Library/Java/JavaVirtualMachines/jdk1.8.0.jdk/Contents/Home

It seems it recognizes all available JVMs and picks the home directory from the latest version.

Setting JAVA_HOME for Mathematica

I'm a heavy user of Mathematica. As of Mathematica 9, it is developed based on Java 6 and its Java related functionalities such as J/Link package may not work properly if a different version of Java is used.

There are two configurations to set and/or check.

JAVA_HOME

As of Mathematica 9, verify that Mathematica's $JAVA_HOME is pointing to macOS's system Java's JVM 1.6.*:

In[1]:= Import["!echo $JAVA_HOME", "Text"]

Out[1]= "/System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home"

In[2]:= Environment["JAVA_HOME"]

Out[2]= "/System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home"

I'm not sure why the following does not work:

In[3]:= Import["!java -version", "Text"]

Out[3]= ""

CommandLine -> "java"

One can "install" Java inside Mathematica runtime by the function InstallJava and then use Java classes inside Mathematica programs.

The InstallJava function or its close relative ReinstallJava has an option called CommandLine:

CommandLine -> "cmd"    use the specified command line to launch the Java runtime, instead of "java"

Some examples of that is

InstallJava[]

InstallJava[CommandLine -> "java"]

InstallJava[CommandLine -> "java --Xmx1024m"]

The source code in $InstallationDirectory/SystemFiles/Links/JLink/Kernel/InstallJava.m indicates that if CommandLine is not used, it will uses Mathematica's own Java ToFileName[{getJLinkAppDir[], "JLink.app", "Contents", "MacOS"}, "JavaApplicationStub"]. If CommandLine -> "java" is used, make sure it's the right version:

In[8]:= Needs["JLink`"]
ReinstallJava[CommandLine->"java"]
LoadJavaClass["java.lang.System"]
java`lang`System`getProperty["java.version"]
Out[9]= LinkObject[java -classpath "/Applications/Mathematica.app/SystemFiles/Links/JLink/JLink.jar" -Xdock:name=J/Link -Xmx256m  -Djava.system.class.loader=com.wolfram.jlink.JLinkSystemClassLoader com.wolfram.jlink.Install -init "/tmp/m00000347291",166,4]
Out[10]= JavaClass[java.lang.System,<>]
Out[11]= 1.6.0_65

If the output of getProperty["java.version"] is not consistent with JAVA_HOME, or if LoadJavaClass["java.lang.System"] issues errors, there must be some problem.

See the attached notebook containing these testing code.

Methods for starting Mathematica

open -a Mathematica

If I start Mathematica with open -a Mathematica from command line, which would lead Mathematica to inherit JAVA_HOME set in .bashrc, I get the correct JAVA_HOME value

In[1]:= Import["!echo $JAVA_HOME", "Text"]

Out[1]= "/System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/\
Home"

In[2]:= Environment["JAVA_HOME"]

Out[2]= "/System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/\
Home"

as well as correct version of Java:

In[16]:= Needs["JLink`"]
ReinstallJava[CommandLine -> "java"]
LoadJavaClass["java.lang.System"]
java`lang`System`getProperty["java.version"]

Out[17]= LinkObject["'/Applications/Mathematica.app/SystemFiles/Links/JLink/JLink.app/Contents/MacOS/JavaApplicationStub' -init \"/tmp/m00000847291\"", 219, 4]

Out[18]= JLink`JavaClass["java.lang.System", 0, {JLink`JVM["vm1"],JLink`JVM["vm2"]}, 1, "java`lang`System`", False, True]

Out[19]= "1.6.0_65"

At the same time Oracle JDK 1.7 and 1.8 are installed on the system.

Double clicking "/Applications/Mathematica.app"

If I start Mathematica by double clicking "/Applications/Mathematica.app" in Finder or a link to it in Dock,

ReinstallJava[CommandLine -> "java"]
LoadJavaClass["java.lang.System"]

issues a LinkObject::linkn error, and Environment["JAVA_HOME"] returns $Failed:

In[1]:= Needs["JLink`"]
ReinstallJava[CommandLine->"java"]
LoadJavaClass["java.lang.System"]
java`lang`System`getProperty["java.version"]
Out[2]= LinkObject[java -classpath "/Applications/Mathematica.app/SystemFiles/Links/JLink/JLink.jar" -Xdock:name=J/Link -Xmx256m  -Djava.system.class.loader=com.wolfram.jlink.JLinkSystemClassLoader com.wolfram.jlink.Install -init "/tmp/m00000155721",125,4]
During evaluation of In[1]:= LinkObject::linkn: Argument LinkObject[java -classpath "/Applications/Mathematica.app/SystemFiles/Links/JLink/JLink.jar" -Xdock:name=J/Link -Xmx256m  -Djava.system.class.loader=com.wolfram.jlink.JLinkSystemClassLoader com.wolfram.jlink.Install -init "/tmp/m00000155721",125,4] in LinkReadyQ[LinkObject[java -classpath "/Applications/Mathematica.app/SystemFiles/Links/JLink/JLink.jar" -Xdock:name=J/Link -Xmx256m  -Djava.system.class.loader=com.wolfram.jlink.JLinkSystemClassLoader com.wolfram.jlink.Install -init "/tmp/m00000155721",125,4]] has an invalid LinkObject number; the link may be closed. >>
During evaluation of In[1]:= LinkObject::linkn: Argument LinkObject[java -classpath "/Applications/Mathematica.app/SystemFiles/Links/JLink/JLink.jar" -Xdock:name=J/Link -Xmx256m  -Djava.system.class.loader=com.wolfram.jlink.JLinkSystemClassLoader com.wolfram.jlink.Install -init "/tmp/m00000155721",125,4] in LinkConnectedQ[LinkObject[java -classpath "/Applications/Mathematica.app/SystemFiles/Links/JLink/JLink.jar" -Xdock:name=J/Link -Xmx256m  -Djava.system.class.loader=com.wolfram.jlink.JLinkSystemClassLoader com.wolfram.jlink.Install -init "/tmp/m00000155721",125,4]] has an invalid LinkObject number; the link may be closed. >>
During evaluation of In[1]:= LinkObject::linkn: Argument LinkObject[java -classpath "/Applications/Mathematica.app/SystemFiles/Links/JLink/JLink.jar" -Xdock:name=J/Link -Xmx256m  -Djava.system.class.loader=com.wolfram.jlink.JLinkSystemClassLoader com.wolfram.jlink.Install -init "/tmp/m00000155721",125,4] in LinkReadyQ[LinkObject[java -classpath "/Applications/Mathematica.app/SystemFiles/Links/JLink/JLink.jar" -Xdock:name=J/Link -Xmx256m  -Djava.system.class.loader=com.wolfram.jlink.JLinkSystemClassLoader com.wolfram.jlink.Install -init "/tmp/m00000155721",125,4]] has an invalid LinkObject number; the link may be closed. >>
During evaluation of In[1]:= General::stop: Further output of LinkObject::linkn will be suppressed during this calculation. >>
During evaluation of In[1]:= InstallJava::fail: A link to the Java runtime could not be established. >>
During evaluation of In[1]:= LoadJavaClass::fail: Java failed to load class java.lang.System. >>
Out[3]= $Failed
Out[4]= java`lang`System`getProperty[java.version]

I don't fully understand what causes the LinkObject::linkn error and its possible relation to JAVA_HOME. My guess is this is due to JAVA_HOME not being correctly set for Mathematica and and somewhere in the processing an implied and incorrect Java home is used, possibly computed by

$ /usr/libexec/java_home
/Library/Java/JavaVirtualMachines/jdk1.8.0.jdk/Contents/Home

For both ways of starting Mathematica,

ReinstallJava[]  (* notice there is NO CommandLine -> "java" used *)
LoadJavaClass["java.lang.System"]

works. This is probably expected as CommandLine -> Automatic seems to lead Mathematica to use its own Java $InstallationDirectory/SystemFiles/Links/JLink/JLink.app/Contents/MacOS/JavaApplicationStub. The logic controlling this can be found in source file $InstallationDirectory/SystemFiles/Links/JLink/Kernel/InstallJava.m.

So if you have multiple Java installed and if /usr/libexec/java_home finds the wrong version of Java home directory for Mathematica (i.e. not 1.6.*)

$ /usr/libexec/java_home
/Library/Java/JavaVirtualMachines/jdk1.8.0.jdk/Contents/Home

you'll need to start Mathematica with open -a Mathematica.

Wrapper application OpenMathematicaAppFromCLIWithJava1.6.app made with Automator

If you prefer double clicking an icon on Dock than opening terminal and typing open -a Mathematica, you can create an application equivalent to setting JAVA_HOME and open -a Mathematica and put a link to it in Dock.

1) Start /Applications/Automator.app by double clicking it;

2) Choose "Application" and press button "Choose";

3) In "Variables" input field, type "Run Shell Script", and double click it;

4) In the RHS window, replace the default content 'cat' with

export JAVA_HOME=$(/usr/libexec/java_home -v 1.6*)  
open -a "/Applications/Mathematica.app"

5) Save it somewhere as a standalone application. I chose name OpenMathematicaAppFromCLIWithJava1.6.app;

6) Optionally, you can make the icon of OpenMathematicaAppFromCLIWithJava1.6.app same as Mathematica.app's by clicking "Get Info" in the context menu of the two applictions, and copy the icon in the top left part of the pop-up window by selecting the icon by clicking on it and Cmd-C and Cmd-V;

7) Drag OpenMathematicaAppFromCLIWithJava1.6.app onto Dock to create a link to it;

8) Start Mathematica by clicking the icon on Dock, and verify that Environment["JAVA_HOME"] and getProperty[java.version] behave correctly.

Configuring IDEs (virtually Eclipse and IntelliJ IDEA)

In IDEs such as Eclipse and IntelliJ IDEA, it's actually easier to use multiple versions of JDK, and different versions for different projects/modules. It's fairly easy to find the related documentation. My understanding is IDEs' JDK version does not have to be same as command-line java. They are basically different and unrelated Java development environments.

A relatively more complex issue is, as Eclipse and IntelliJ IDEA themselves are Java applications, what JVM are they running off of? And do you possibly want to start them using Oracle Java?

Here are some information:

IntelliJ IDEA

Selecting the JDK version the IDE will run under.

Eclipse

(This part about Eclipse is a drat and needs verification.)

Method 1: -vm in Eclipse.ini

Add something like

-vm /Library/Java/JavaVirtualMachines/jdk1.7.0_45.jdk/Contents/Home/

at the end of eclipse.ini.

Method 2: shell script + Automator application

Make a shell script that takes care of JAVA_HOME and JVM:

#!/bin/sh
export JAVA_HOME=$(/usr/libexec/java_home -v 1.7)
LAUNCHER_JAR=/Applications/eclipse/plugins/org.eclipse.equinox.launcher_1.2.0.v20110502.jar

java \
-showversion \
-XX:MaxPermSize=256m \
-Xms1024m \
-Xmx1024m \
-Xdock:icon=/Applications/eclipse/Eclipse.app/Contents/Resources/Eclipse.icns \
-XstartOnFirstThread \
-Dorg.eclipse.swt.internal.carbon.smallFonts \
-Dosgi.requiredJavaVersion=1.5 \
-jar $LAUNCHER_JAR

and then make a wrapper application using Automator.

Installing Oracle JDK from command-line

  • Download DMG

    $ wget --no-cookies --no-check-certificate --header "Cookie: gpw_e24=http%3A%2F%2Fwww.oracle.com%2F; oraclelicense=accept-securebackup-cookie" "http://download.oracle.com/otn-pub/java/jdk/8u60-b27/jdk-8u60-macosx-x64.dmg"

  • Mount DMG:

    $ hdiutil mount jdk-8u60-macosx-x64.dmg

  • Install

    $ sudo installer -pkg /Volumes/JDK\ 8\ Update\ 60/JDK\ 8\ Update\ 60.pkg -dominfo LocalSystem $ sudo installer -pkg /Volumes/JDK\ 8\ Update\ 60/JDK\ 8\ Update\ 60.pkg -target LocalSystem

References

blog comments powered by Disqus