Calling Java code from R

Introduction

In the previous post I looked at some simple methods for calling C code from R using a simple Gibbs sampler as the motivating example. In this post we will look again at the same Gibbs sampler, but now implemented in Java, and look at a couple of options for calling that code from an R session.

Stand-alone Java code

Below is some Java code for implementing the bivariate Gibbs sampler discussed previously. It relies on Parallel COLT, which must be installed and in the Java CLASSPATH in order to follow the examples.

import java.util.*;
import cern.jet.random.tdouble.*;
import cern.jet.random.tdouble.engine.*;

class Gibbs
{

    public static void main(String[] arg)
    {
	if (arg.length != 3) {
            System.err.println("Usage: java Gibbs <Iters> <Thin> <Seed>");
            System.exit(1);  
        }
	int N=Integer.parseInt(arg[0]);
	int thin=Integer.parseInt(arg[1]);
	int seed=Integer.parseInt(arg[2]);
	DoubleRandomEngine rngEngine=new DoubleMersenneTwister(seed);
	Normal rngN=new Normal(0.0,1.0,rngEngine);
	Gamma rngG=new Gamma(1.0,1.0,rngEngine);
	double x=0,y=0;
	System.out.println("Iter x y");
	for (int i=0;i<N;i++) {
	    for (int j=0;j<thin;j++) {
		x=rngG.nextDouble(3.0,y*y+4);
		y=rngN.nextDouble(1.0/(x+1),1.0/Math.sqrt(x+1));
	    }
	    System.out.println(i+" "+x+" "+y);
	}
    }

}

It can be compiled and run stand-alone from an OS shell with the following commands:

javac Gibbs.java
java Gibbs 10 1000 1

As discussed in the previous post, it is possible to call any command-line program from inside an R session using the system() command. A small wrapper function for conveniently running this code from within R can be written as follows.

gibbs<-function(N=10000,thin=500,
             seed=trunc(runif(1)*1e6),
             exec="Gibbs",
             tmpfile=tempfile())
{
  command=paste("java",exec,N,thin,seed,">",tmpfile)
  system(command)
  read.table(tmpfile,header=TRUE)
}

This can then be run from within an R session with a simple call to gibbs(). Note that a random seed is being generated within R to be passed to the Java code to be used to seed the COLT random number generator used within the Java code. As previously discussed, for many long running codes, this approach can be quite effective, and is clearly very simple. However, there is an overhead associated with the system() call, and also with writing output to disk and then reading it back again.

Using rJava

It is possible to avoid the overheads associated with the above approach by directly calling the Java code from R and having the return values returned directly into the R session from memory. There isn’t really direct support for this within the core R language, but there are couple of different solutions provided by R packages. The simplest and most popular approach seems to be the rJava package. This package can be installed with a simple

install.packages("rJava")

This should “just work” on some OSs (eg. Windows), but may fail on other OSs if R is not aware of the local Java environment. If the installation fails, check the error message carefully for advice/instructions. On most Linux systems, the problem can be fixed by quitting R, then running the following command from the shell

sudo R CMD javareconf

before re-starting R and re-attempting the installation. rJava provides a mechanism for starting a JVM within the running R session, creating objects, calling methods and having method return values returned to R. It is actually much more flexible than the .C() function for C code discussed in the previous post.

In order to use this package for our example, we must first re-factor the code slightly in the following way.

import java.util.*;
import cern.jet.random.tdouble.*;
import cern.jet.random.tdouble.engine.*;

class GibbsR
{

    public static void main(String[] arg)
    {
	if (arg.length != 3) {
            System.err.println("Usage: java GibbsR <Iters> <Thin> <Seed>");
            System.exit(1);  
        }
	int N=Integer.parseInt(arg[0]);
	int thin=Integer.parseInt(arg[1]);
	int seed=Integer.parseInt(arg[2]);
	double[][] mat=gibbs(N,thin,seed);
	System.out.println("Iter x y");
	for (int i=0;i<N;i++) {
	    System.out.println(""+i+" "+mat[0][i]+" "+mat[1][i]);
	}	
    }

    public static double[][] gibbs(int N,int thin,int seed)
    {
	DoubleRandomEngine rngEngine=new DoubleMersenneTwister(seed);
	Normal rngN=new Normal(0.0,1.0,rngEngine);
	Gamma rngG=new Gamma(1.0,1.0,rngEngine);
	double x=0,y=0;
	double[][] mat=new double[2][N];
	for (int i=0;i<N;i++) {
	    for (int j=0;j<thin;j++) {
		x=rngG.nextDouble(3.0,y*y+4);
		y=rngN.nextDouble(1.0/(x+1),1.0/Math.sqrt(x+1));
	    }
	    mat[0][i]=x; mat[1][i]=y;
	}
	return mat;
    }

}

This code can be compiled and run from the command-line just as the previous code could.

javac GibbsR.java
java GibbsR 10 1000 1

However, we have now separated out the code we want to be able to call from R into a static method called gibbs, which runs the Gibbs sampler and stores the result in a 2-dimensional array which is its return value. We can now see how to call this code from within a running R session. We first need to set up the R environment ready to call the code.

library(rJava)
.jinit()
obj=.jnew("GibbsR")

Line 1 loads the package, line 2 starts up the JVM, and line 3 creates a link to the the GibbsR class (in general this is used to create a new Java object of the given type, but here we are using static methods). Java methods are called on Java objects using .jcall(). We can write a simple R function to conveniently call the method as follows.

jgibbs<-function(N=10000,thin=500,seed=trunc(runif(1)*1e6))
{
    result=.jcall(obj,"[[D","gibbs",as.integer(N),as.integer(thin),as.integer(seed))
    mat=sapply(result,.jevalArray)
    mat=cbind(1:N,mat)
    colnames(mat)=c("Iter","x","y")
    mat
}

This can now be called with a simple jgibbs(). The first line of the function body carries out the actual method call. The return type of the method must be explicitly declared – “[[D” means a 2-dimensional array of doubles, using JNI notation. Care must also be taken to coerce the method parameters into the correct type that the Java method expects to receive. .jcall() is generally quite good at unpacking basic Java types into corresponding R types. However, the two dimensional array is here returned as an R list consisting of one-dimensional Java array objects. The unpacking is completed using the subsequent call to jevalArray() using sapply(), before the resulting matrix is tidied up and returned to the R session.

Summary and further reading

We have looked at a couple of very simple methods for calling Java code from an R session. The rJava package is a very flexible mechanism for integrating Java code into R.

I haven’t found a lot of tutorial-level material on the web for the rJava package. However, the package itself has very good documentation associated with it. Start with the information on the rJava home page. From an R session with the rJava package loaded, help(package="rJava") lists the available functions, all of which have associated documentation. ?.jinit, ?.jnew, ?.jcall and ?.jevalArray provide further background and information on the example covered here.

After that, the source code of R packages which use rJava are a useful source of further inspiration – look at the reverse-depends list for rJava in CRAN. In particular, the helloJavaWorld package is a tutorial for how to include Java code in an R package (read the associated vignette).

Published by

darrenjw

I am Professor of Statistics within the Department of Mathematical Sciences at Durham University, UK. I am an Bayesian statistician interested in computation and applications, especially to engineering and the life sciences.

33 thoughts on “Calling Java code from R”

  1. This is my first time i visit here. I wanted to thank you for this great read!! I definitely enjoying every little bit of it and love learning more on this topic. This is my first time i visit here. I found so many interesting stuff in your blog, it’s really helpful for me.

  2. Hi, Darren! I found your blog accidentally. You really made excellent posts on many topics. I’m also very interested about using Java in R. I’ve question about your code here. You said we can use the following code:

    library(rJava)
    .jinit()
    obj=.jnew(“GibbsR”)

    My question is that where should we put the file “GibbsR.class”? In the current R working directory? I tried this, but it seems that it doesn’t work. R says no definition for class “MyClass” is found. Could you explain a little bit more on this for me?

  3. I guess just anywhere in your Java CLASSPATH. For me it certainly works in the current directory, but then I have “.” in my $CLASSPATH.

  4. I am having similar difficulty to one of the previous posters. I have specified a ,jinit(classpath… that seems to return a code indicating success. When I run .jnew however i get the error

    java.lang.ClassNotFOundException

    My code:

    library(rJava)
    .jinit(classpath=”C:/Users/jch1748/Documents/Projects/W2009028 – Pattern Value Simulation Study/Rsimple.jar”)
    s <- .jnew(“Rsimple”)

    Trying to figure out why I get the error. The Java programmer did not use the same statements inside the Java code to define class and methods. Are those critical or can they be anything that Java allows?

    1. Yeah, I have the same problem! Though I have a .class file and use

      library(rJava)
      .jinit(classpath=getwd()) # This is definitely the right location
      obj <- .jnew("NewWindow")
      
  5. i cannot get ur point, can u show other simple example?
    my task is : get an input value from java and pass the value to R . Then in R, add input value with one then pass the (input+1) value back to java.
    this is what i wan to do…..

    1. The post is about calling Java from R. It seems that you want to call R from Java. This is also possible, but not something I’ve done. I think you can do it using RSJava, and the previous commenter mentioned another possibility.

  6. Thank you for the great article. It has been a huge help. For those of you having a few problems, here are some things that helped me. I have been working with R a lot, and am pretty new to java. Some of these may be obvious.

    1) to pass a 2d matrix, try using .jarray(MyMatrix,dispatch=T). The “dispatch=T” seems to make sure it does go in as 2d.

    2) as.double(MyMatrix) does not seem to always do the trick. Each element must be of the correct format.

    3) .jclassPath() shows you all the current class paths. Another can easily be added using .jaddClassPath(path). You can easily add reference to a “.jar” this way. Don’t forget to reference the class with “package.class”. The class name alone will not do it.

  7. library(rJava)
    > .jinit(classpath=”C:\Code-sequentialpattern Mining\SPMF.jar”)
    Error: unexpected input in “.jinit(classpath=””
    > s <- .jnew(“SPMF.jar”)

    Hi..i am getting above..when i am calling java from R..i have installed RJava package
    I have given correct path
    Kindly help me..

  8. Thanks a lot. Successfully called Java code from R, after a lot of trials and errors on calling a Java function which returning a vector of complex objects. However, still haven’t figured out how to call from R a Java function which returns a list of objects.

  9. Thank you so much, I have been looking for an example on how to translate a Java matrix to a R matrix. You sapply example did it.

  10. Thank you for the great article. It has been a huge help. But I encountered some problem, when calling .jar file from R.
    First, I wrote a very simple example in java, and generated a .jar file named Add_add.jar.

    public class Add_add{
    public static void main(String[] args) {
    … // initial variable a and b
    int result = calc(a,b);
    }
    public static int calc(int a, int b){
    int c = a + b;
    return c;
    }
    }

    Second I set up the R environment ready to call the code.
    >library(rJava)
    > .jinit(classpath=”C:\\Users\\…\\Add_add.jar”)
    > jobject .jcall(jobject ,”I”,”calc”,as.integer(2),as.integer(3))

    Then there is an error like this:
    Error in .jcall(jobject, “I”, “calc”, as.integer(2), as.integer(3)) : method calc with signature (II)I not found

    I am so confused that why it cannot be found. Could you please give me a suggestion how to fix it?
    Thank you very much!

  11. classes I need are in a package called “spaces” which is in a subfolder of my “app.jar”. And I can not access it:

    > library (rjava)
    >. jinit (classpath = “app.jar”)
    >. jpackage (spaces, “app / microbes / app2”)
    > obj =. jnew (“Class1”)

    Here “app / microbes / app2” is the way to access the package spaces

    but R found neither the package nor spaces Class1
    Could someone help me?
    Thank you

  12. Error in .jnew(“class”) : java.lang.ClassNotFoundException …error found while calling java code in R how to resolve any solution pls..THANKS IN ADVANCE

  13. Hey, I have the same problems. I need to call CLARANS.java in R: https://haifengl.github.io/smile/doc/smile/clustering/CLARANS.html

    I only get:
    library(rJava)
    .jinit()
    .jaddClassPath(“clustering.jar”)
    claransnew <- .jnew('java.lang.Object')
    .jcall(claransnew, returnSig="V", method="CLARANS")
    Fehler in .jcall(claransnew, returnSig = "V", method = "CLARANS") :
    method CLARANS with signature ()V not found

    I tried different "returnSig", but there's always been the same error.
    Where's the mistake?

  14. Hello ,
    I am new in R as well as java. i just started my career with one company. So my manager has given me one task that integrate R server, studio with java ecilips.
    I have R code (calculation) and also java code( UI). let me explain what i want.
    java code—
    In UI there is one browse button and one out put button. i browse one .csv file now when i will click to output button i want that file should go to R code as a input and after that R code will run after that the result should display in java ecilips.
    I spend more time in searching but i did not get any understandable code and article.
    Can some one help me please.
    Thank you

  15. This was a great help for getting the system commands setup. I didn’t end up using the tmpfile, but used this to get the data back to R:

    return(read.table(system(command,intern=TRUE)))

    Thanks again!

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.