[Rd] rJava question

Simon Urbanek simon.urbanek at r-project.org
Tue Dec 28 20:05:46 CET 2010


On Dec 27, 2010, at 11:56 PM, Dominick Samperi wrote:

> After some trial and error I figured out how to pass matrices from R to java
> and back using rJava, but this method is not documented and I wonder if there is a
> better way?

stats-rosuda-devel is the rJava list you want to use.

> Anyway, here is what I found works:
> (m = matrix(as.double(1:12),3,4))
> [shows m as you would expect]
> jtest <- .jnew("JTest")
> (v <- .jcall(jtest, '[[D], 'myfunc', .jarray(m), evalArray=FALSE))
> [shows v = m + 10]
> Here the JTest class has a method named myfunc that accepts
> a double[][] and returns a double[][]. It simply adds 10 to every
> element.

The above is plain wrong (well, that's actually a guess since you didn't provide even the signature of the method) - matrices in R are vectors, so the type is double[]. In Java there is no matrix type, so it's up to the application to represent matrices and there are many ways - some more efficient than others. From your example above it seems that you are using double[][] -- so you have to allocate the extra objects one way or another (that's why it's inefficient to represent matrices that way).

But from your e-mail I have the feeling that your questions is rather about calling a method that returns double[][], so for example:
public static double[][] pass();
where double[][] is a rectangular array (i.e. length of all inner arrays is equal).

Unfortunately .jcall is a bit inconsistent due to bug that was introduced with the new J() API. So the intended behavior is (using class Test with the method above):
> J("Test")$pass()
     [,1] [,2] [,3] [,4]
[1,]    1    2    3    4
[2,]    5    6    7    8
[3,]    9   10   11   12
[4,]   13   14   15   16

The $ operator makes sure that the result is converted to a native R form where possible, including recursive structures like double[][].

However, the intention of .jcall() was to never perform recursive evaluation, so this is intended:

> .jcall("Test","[[D","pass", evalArray=TRUE)
[1] "Java-Array-Object[D:[D at 11ddcde"

[1] "Java-Array-Object[D:[D at 18fb1f7"

[1] "Java-Array-Object[D:[D at ed0338"

[1] "Java-Array-Object[D:[D at 6e70c7"

The intended behavior (and true in older version of rJava) was for .jcall with evalArray=FALSE to return the reference:

> .jcall("Test","[[D","pass", evalArray=FALSE)
[1] "Java-Array-Object[[D:[[D at 8f4fb3"

Unfortunately, the bug is that .jcall uses rJava:::newArray() to create the reference which defaults to simplify=TRUE so the current (buggy) behavior is:

> .jcall("Test","[[D","pass", evalArray=FALSE)
     [,1] [,2] [,3] [,4]
[1,]    1    2    3    4
[2,]    5    6    7    8
[3,]    9   10   11   12
[4,]   13   14   15   16

The real issue is that:
a) if the bug is fixed, .jcall() can return just the reference which is intended
b) there is currently no exposed API for rJava:::newArray so the simplification is not available in any form for references if the bug is fixed (other than using the J/$ API).

That's why I was hesitant so far to fix the bug, but I really should -- which is why the behavior your discovered will change. However, then I need to add some API to be able to convert a reference in the same way that rJava:::newArray provides and expose it - I didn't think through that part, so that's why I got stuck.

I hope it helps...

(PS: please continue any discussion on stats-rosuda-devel)

> The parameter 'evalArray' is confusing because when
> evalArray=TRUE the result is NOT evaluated (a list is returned
> that you then have to apply .jevalArray to do get the answer).
> There seems to be an option to have a java reference returned
> instead of the actual matrix. Can the R side manipulate the
> matrix (on the java side) through this reference?
> Thanks,
> Dominick
> 	[[alternative HTML version deleted]]
> ______________________________________________
> R-devel at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel

More information about the R-devel mailing list