Skip to content

Instantly share code, notes, and snippets.

@jirutka
Last active November 15, 2015 17:40
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jirutka/ab8ccaf40e10773cb17f to your computer and use it in GitHub Desktop.
Save jirutka/ab8ccaf40e10773cb17f to your computer and use it in GitHub Desktop.
Hack to force rJava to use specific Java VM, i.e. get rid of “Unsupported major.minor version 52.0!”
#!/bin/bash
# vim: set ts=4:
#
# This is free and unencumbered software released into the public domain.
#
# Anyone is free to copy, modify, publish, use, compile, sell, or
# distribute this software, either in source code form or as a compiled
# binary, for any purpose, commercial or non-commercial, and by any
# means.
#
# -----BEGIN HELP-----
# This script is a hack to force rJava to use specific Java VM on OS X.
#
# Before you use this script, you should run R javareconf and reinstall rjava:
# $ R CMD javareconf JAVA_HOME="$(/usr/libexec/java_home -v 1.8)"
# $ R
# > install.packages('rJava', type='source')
#
# After that, if rJava keeps throwing "Unsupported major.minor version 52.0",
# try this hack.
#
# Usage:
# @SCRIPT_NAME@
# @SCRIPT_NAME@ [--revert | --java-version VERSION | --java-home JAVA_HOME]
#
# Options:
# --revert Revert changes in rJava.so, i.e. link it back to
# Apples' dynamic re-executor.
# --version VERSION Java version to use; 1.6, 1.7, or 1.8 (default: 1.8).
# --java-home JAVA_HOME Home directory of specific Java VM (e.g.:
# /Library/Java/JavaVirtualMachines/jdk1.8.0u60-b07.jdk/Contents/Home)
#
# Sources:
# https://gist.github.com/jirutka/ab8ccaf40e10773cb17f
# https://github.com/s-u/rJava/issues/37
# https://lists.apple.com/archives/java-dev/2008/Aug/msg00181.html
# -----END HELP-----
DEFAULT_LIBJVM_PATH='/System/Library/Frameworks/JavaVM.framework/Versions/A/JavaVM'
SCRIPT_NAME="$(basename "$0")"
revert=
java_version='1.8'
java_home=
die() {
echo "$1" >&2
exit 1
}
usage() {
cat "$0" \
| sed -En '/-{5}BEGIN HELP-{5}/,/-{5}END HELP-{5}/p' \
| sed -E "s/^# ?//; 1d;\$d; s/@SCRIPT_NAME@/${SCRIPT_NAME}/"
}
case $1 in
--revert)
revert='true'
shift
;;
--java-home)
java_home="$2"
shift 2
;;
--version)
java_version="$2"
shift 2
;;
-h | --help)
usage
exit 0
;;
esac
if [ $# -gt 0 ]; then
usage
exit 1
fi
lib_paths="$(R --vanilla --quiet -e '.libPaths()' | sed -n 's/\[[0-9]\] "\([^"]*\)"/\1/p')"
if [ -n "$lib_paths" ]; then
echo "Found R libPaths: $(echo $lib_paths)"
else
die 'ERROR: Failed to find R libPaths.'
fi
rjavaso_file="$(find $lib_paths -name rJava.so | head -n 1)"
if [ -e "$rjavaso_file" ]; then
echo "Found rJava.so in: $rjavaso_file"
else
die 'ERROR: Could not find rJava.so file.'
fi
libjvm_old=$( otool -L "$rjavaso_file" | grep -E '(JavaVM|libjvm\.dylib)' | sed -En "s|^[^/]+(/.*) \(comp.*$|\1|p" )
if [ -e "$libjvm_old" ]; then
echo "rJava.so is currently linked with: $libjvm_old"
else
die 'ERROR: Failed to find Java shared library in rJava.so.'
fi
if [ "$revert" = 'true' ]; then
libjvm_new="$DEFAULT_LIBJVM_PATH"
else
[ -n "$java_home" ] || java_home="$(/usr/libexec/java_home -v $java_version)" || die
libjvm_new="${java_home}/jre/lib/server/libjvm.dylib"
fi
if [ -e "$libjvm_new" ]; then
echo "We're going to re-link it against: $libjvm_new"
else
die "ERROR: File '$libjvm_new' doesn't exist."
fi
maybe_sudo=''
[ -O "$rjavaso_file" ] || maybe_sudo='sudo'
$maybe_sudo install_name_tool -change "$libjvm_old" "$libjvm_new" "$rjavaso_file" || die
echo ''
if [ "$revert" = 'true' ]; then
echo "Hack reverted, rJava has been linked back to Apple's dynamic re-executor."
else
cat <<-EOF
Success! rJava should finally use correct Java VM.
================================================================================
! Keep in mind that this is just a nasty hack. We've bypassed Apple's dynamic !
! re-executor and linked rJava.so directly with specific Java version. The !
! downside is that you have to fix it again after every Java and rJava update! !
================================================================================
If you want to revert this change, run: $0 --revert
EOF
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment