Skip to content

Instantly share code, notes, and snippets.

@hogmoru
Last active September 20, 2023 08:15
Show Gist options
  • Star 50 You must be signed in to star a gist
  • Fork 9 You must be signed in to fork a gist
  • Save hogmoru/8e02cf826c840914a8ed93fd418ed88e to your computer and use it in GitHub Desktop.
Save hogmoru/8e02cf826c840914a8ed93fd418ed88e to your computer and use it in GitHub Desktop.

Technical details for https://stackoverflow.com/a/44169445/6730571

Details of investigation:

On a base system, /usr/bin/java is a symlink that points to /System/Library/Frameworks/JavaVM.framework/Versions/Current/Commands/java, which is an Apple wrapper tool that locates and executes the actual java.

(Do not touch anything in those 2 system directories. It should actually be impossible due to "System Integrity Protection" anyway.)

If you don't have Java installed, attempting to execute java will open a dialog that invites you to install it.

If you install a JDK from Oracle or OpenJDK pkg download, it goes to /Library/Java/JavaVirtualMachines (1), and java will find it.

When you have several of them, you can use /usr/libexec/java_home as explained in other answers to help set $JAVA_HOME for current shell.

If $JAVA_HOME is set, and points to a valid JDK, Apple's java wrapper will use it.

But how do we chose the default version, the one that executes without setting $JAVA_HOME?

The old "Java Preferences pane" used to allow exactly that, but it does not exist anymore since 10.8.2.

By default, it seems the wrapper checks all JREs under /Library/Java/JavaVirtualMachines (2) and runs the one with highest version (3).

I don't want that, if the latest is too "cutting edge" (e.g. JDK9 at the moment breaks groovyConsole & other tools).

So, for example, to exclude JDK9 from consideration by system java wrapper, rename /Library/Java/JavaVirtualMachines/jdk-9.jdk/Contents/Info.plist to Info.plist.disabled.

(Editing the file also works, if you know how to convert to xml with plutil, the relevant key is JVMVersion: when I changed it from 9 to -9 or anything that is lower than 1.8.0_131 it was considered "lower" by the wrapper).

As far as I can tell it does not affect anything else. Yes, if I point $JAVA_HOME to that JDK9 it does still work.

There might be an undocumented way to configure this (old versions used to read $HOME/Library/Preferences/java_home.plist but that does not seem to be the case anymore).

(To be continued... ?)


Annex

(1) And also overwrites /Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/. Apparently this is the one that the new Preferences pane will launch -- this is the only exception I found to my solution: that thingy will still use JDK9 (latest I installed), but no other Java application does.


(2) To find this I used opensnoop and followed what happened when executing java -version. That gave clues about which files to check, and upon investigating I found that I was not alone :) Lots of clues, but sadly no exploitable conclusion on that page. I think the guy was using a pre-ElCapitan macOS.

Also used "verbose" mode for java launcher:

$ JAVA_LAUNCHER_VERBOSE=true java -version
2017-05-24 23:15:14.064 java[15602:731042] [JVM Detection] AddJVMsFromLibraryPath: Scanning: file:///Users/asmithee/Library/
2017-05-24 23:15:14.065 java[15602:731042] [JVM Detection] AddJVMsFromLibraryPath: Scanning: file:///Users/asmithee/Developer/
2017-05-24 23:15:14.065 java[15602:731042] [JVM Detection] AddJVMsFromLibraryPath: Scanning: file:///Library/
2017-05-24 23:15:14.066 java[15602:731042] [JVM Detection] AddJVMsFromSampledFile: Checking for a JVM at: libjli.dylib -- file:///Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/MacOS/
2017-05-24 23:15:14.066 java[15602:731042] [JVM Detection] Match: Could not find constraint for JVMMaximumSystemVersion
2017-05-24 23:15:14.066 java[15602:731042] [JVM Detection] Match: Could not find constraint for JVMMaximumFrameworkVersion
2017-05-24 23:15:14.066 java[15602:731042] [JVM Detection] AddJVMsFromSampledFile: JVM has capabilities: (
    CommandLine
)
2017-05-24 23:15:14.067 java[15602:731042] [JVM Detection] AddJVMsFromSampledFile: Checking for a JVM at: libjli.dylib -- file:///Library/Java/JavaVirtualMachines/jdk1.8.0_74.jdk/Contents/MacOS/
2017-05-24 23:15:14.067 java[15602:731042] [JVM Detection] Match: Could not find constraint for JVMMaximumSystemVersion
2017-05-24 23:15:14.069 java[15602:731042] [JVM Detection] Match: Could not find constraint for JVMMaximumFrameworkVersion
2017-05-24 23:15:14.070 java[15602:731042] [JVM Detection] AddJVMsFromSampledFile: JVM has capabilities: (
    CommandLine
)
2017-05-24 23:15:14.070 java[15602:731042] [JVM Detection] AddJVMsFromLibraryPath: Scanning: file:///Developer/
2017-05-24 23:15:14.070 java[15602:731042] [JVM Detection] AddJVMsFromLibraryPath: Scanning: file:///System/Library/
2017-05-24 23:15:14.070 java[15602:731042] [JVM Detection] AddJVMsFromLibraryPath: Scanning: file:///Developer/
available JVMs:
    1.8.0_131, x86_64:	"Java SE 8"	/Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home
    1.8.0_74, x86_64:	"Java SE 8"	/Library/Java/JavaVirtualMachines/jdk1.8.0_74.jdk/Contents/Home

obtained version: "1.8.0_131"
set preferred architecture to: "x86_64"
about to exec: "/Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home"
java version "1.8.0_131"
Java(TM) SE Runtime Environment (build 1.8.0_131-b11)
Java HotSpot(TM) 64-Bit Server VM (build 25.131-b11, mixed mode)
Copy link

ghost commented Aug 20, 2018

didn't work for Java 10, any clue?

@tmasjc
Copy link

tmasjc commented Sep 4, 2018

It works for me. I need to accustom R to both rJava (Java 10) as well as Sparklyr (Java 8). Thanks for your tip.

R version 3.4.4 (2018-03-15)
Platform: x86_64-apple-darwin15.6.0 (64-bit)
Running under: macOS High Sierra 10.13.6

@RaymondSHANG
Copy link

The "/Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/" is the default JRE for other installed softwares. In my case, I need to remove the JavaAppletPlugin.plugin folder, and reinstall java8 to get everything work, and make java8 as my default JRE system-widely.

@trmaphi
Copy link

trmaphi commented Apr 7, 2019

I wrote a short script for only enable chosen jdk gist. Hope it's useful.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment