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).

About these ads

Tags: , , , , , , , , , , , , , , , , , ,

22 Responses to “Calling Java code from R”

  1. application performance monitoring Says:

    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. Ben Says:

    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. darrenjw Says:

    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. Gibbs sampler in various languages (revisited) « Darren Wilkinson's research blog Says:

    [...] It is easy to extend R using C, C++ and Java. I have shown in previous posts how to do this using Java and using C, and the recent post by Dirk shows how to extend using C++. Although interesting, this [...]

  5. Faster Gibbs sampling MCMC from within R « Darren Wilkinson's research blog Says:

    [...] options turn out to be. The post draws heavily on my previous posts on calling C from R and calling Java from R, as well as Dirk Eddelbuettel’s post on calling C++ from R, and it may be helpful to consult [...]

  6. Joe Hightower Says:

    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?

  7. Catalogue of my first 25 blog posts « Darren Wilkinson's research blog Says:

    [...] Calling Java code from R: how to call a Gibbs sampler written in Java from [...]

  8. Sankha Narayan Guria Says:

    sometimes it may be required to call R code from Java… then we can use Java2R. Its a relatively new project at https://github.com/sankha93/java2r

  9. Jess Lim Says:

    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…..

    • darrenjw Says:

      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.

  10. Jess Lim Says:

    i set an example in http://www.mail-archive.com/r-help@stat.math.ethz.ch/msg76159.html

    but an error occur
    Error in .jcall(“my_convolve”, “[D”, “convolve”, x, y) :
    RcallMethod: cannot determine object class

    because the directory of classpath?

  11. R Meets Java: An Absolute Beginners’ Introduction | Gage Theory Says:

    [...] fire up R and load the rJava package. The helloJavaWorld vignette and Darren Wilkinson offer good examples on how to get started for people with some experience with Java. We’ll follow [...]

  12. Adam Says:

    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.

  13. NAD Says:

    i am not able to call my java code in R..i hv installed RJava package..

  14. NAD Says:

    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..

  15. Yanchang Zhao Says:

    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.

  16. Thaddeus Aid Says:

    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.

  17. Thaddeus Aid Says:

    Reblogged this on Thad is NOT food and commented:
    This blog helped me solve an issue that I was having with rJava.

  18. Saisai Says:

    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!

  19. Moi Says:

    You really made excellent posts on many topics.
    Thank you

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s


Follow

Get every new post delivered to your Inbox.

Join 127 other followers

%d bloggers like this: