Search code examples
javarknitrstdoutrjava

Display Java console output in R using rJava


I have created the following Java class and saved it as Test.java, then compiled into Test.class on the command line using javac Test.java:

public class Test {

  public Test() {
  }

  public double power(double number) {
    System.out.println("calculating...");
    return number * number;
  }
}

Furthermore, I have created the following R script and saved it as test.R:

library("rJava")
.jinit(classpath = getwd())
test <- .jnew("Test")
.jcall(test, "D", "power", 3)

When I execute it, for example using R CMD BATCH test.R on the command line, I get the following output, which is what I want:

calculating...
[1] 9

However, when I wrap this script in a Markdown document and compile it using knitr, I lose the message that is printed about the calculation taking place. For example, I save the following script in test.Rmd and compile it using RStudio:

```{r echo=TRUE, warning=TRUE, results='show', message=TRUE}
library("rJava")
.jinit(classpath = getwd())
test <- .jnew("Test")
.jcall(test, "D", "power", 3)
```

This only returns the following output, without the message:

## [1] 9

I read somewhere that the reason is that System.out.println in Java writes to stdout, and whether this is shown in the R console or not depends on the interpreter. For example, the output is shown on Unix systems but not on Windows or in knitr.

My questions:

  1. Is the above interpretation correct?
  2. How can I reliably capture or display the output of System.out.println in R, irrespective of operating system or interpreter?
  3. If that's not possible, what is a better way of designing status messages about the current calculations and progress in Java, such that R can display these messages? Thanks!

Solution

  • I'll take a stab at answering my own question... Looks like the RJava folks actually offer a built-in solution (thanks Simon Urbanek if you read this). On the side of the Java code, there is the LGPL-licensed JRI.jar, which is delivered with rJava (look at the jri sub-directory in the rJava package directory in your local R library path) and which can be copied/extracted into the Java library path. It's only 82kb, so fairly light-weight.

    JRI offers a replacement of the default print stream in Java. Essentially, you redirect the system output into an RConsoleOutputStream provided by JRI. The code in my question above can be modified as follows to print to the R console instead of stdout.

    import java.io.PrintStream;
    import org.rosuda.JRI.RConsoleOutputStream;
    import org.rosuda.JRI.Rengine;
    
    public class Test {
    
      public Test() {
        Rengine r = new Rengine();
        RConsoleOutputStream rs = new RConsoleOutputStream(r, 0);
        System.setOut(new PrintStream(rs));
      }
    
      public double power(double number) {
        System.out.println("calculating...");
        return number * number;
      }
    }