R4.0 with Java 14 inside macOS 10.15.4

As usual, there are some issues with new Java releases (14) and R4.0. If you want to run rJava package inside R you have to do few things.

First, make sure you are using Java 14 as default inside terminal session. Inside ~/.profile or ~/.zshrc add this line

export JAVA_HOME=$(/usr/libexec/java_home -v 14)

Once it’s done, you have to make sure to install XCode – you can find it here: XCode. We will need that. XCode contains SDK that is used while R reconfigures itself – it will try to compile small, JNI based, code.

After XCode is installed, make sure to modify this file: /Library/Frameworks/R.framework/Versions/4.0/Resources/etc/Makeconf.

Try to locate the line that reads

CPPFLAGS = -I/usr/local/include

and replace it with line

CPPFLAGS = -isysroot /Applications/XCode/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/
 -I/usr/local/include

Note! Make sure this is just one line inside Makeconf!

Now, you are ready to configure R. Simply call this one

> sudo R CMD javareconf \
JAVA_HOME=${JAVA_HOME} \
JAVA=${JAVA_HOME}/bin/java \
JAVAC=${JAVA_HOME}/bin/javac \
JAVAH=${JAVA_HOME}/bin/javah \
JAR=${JAVA_HOME}/bin/jar

That’s it. You can now install and use rJava package.

Let’s say you have this simple code

.
`-- src
    `-- somepackage
        `-- StringTest.java

and the content of file is

package somepackage;

public class StringTest {
  public String changeString(String str) {
    return "I have changed the string: " + str;
  }

  public static void main(String [] arg) {
    System.out.println(new StringTest().changeString("Hello"));
  }
}

You can compile it following way.

> javac -d target src/somepackage/StringTest.java
> java -cp target somepackage.StringTest
I have changed the string: Hello
> export CLASSPATH=`pwd`/target

and then, use it inside R.

> R version 4.0.0 (2020-04-24) -- "Arbor Day"
Copyright (C) 2020 The R Foundation for Statistical Computing
Platform: x86_64-apple-darwin17.0 (64-bit)
...
...
...
> install.packages('rJava')
...
...
> library(rJava)
> .jinit()
> obj <- .jnew("somepackage.StringTest")
> s <- .jcall(obj, returnSig="Ljava/lang/String;", method="changeString", "Hello")
> print(s)
[1] "I have changed the string: Hello"
> s <- .jcall(obj, returnSig="V", method="main", c("Hello", "Hello") )
I have changed the string: Hello