使用来自 eclipse 的 rJava/JRI 包时,某些命令在 rtest.java 中失败

some commands failing in rtest.java when using rJava/JRI package from eclipse

我正在尝试使用 Eclipse IDE 从 Java 测试 rJava 包。在测试 rJava/JRI 包中的 rtest.java 时,一些命令失败了,但有些命令成功了。无法理解为什么或如何解决它。以下是系统详情:

OS: Windows 10 64 位,R 版本 3.0.2 (2013-09-25) -- "Frisbee Sailing" 64 位 rJava version:0.9-6, Java: Oracle JDK 1.7, Eclipse 版本: 3.8.2.

以下是 rtest.java 个代码:

import java.io.*;
import java.awt.Frame;
import java.awt.FileDialog;

import java.util.Enumeration;

import org.rosuda.JRI.Rengine;
import org.rosuda.JRI.REXP;
import org.rosuda.JRI.RList;
import org.rosuda.JRI.RVector;
import org.rosuda.JRI.RMainLoopCallbacks;

class TextConsole implements RMainLoopCallbacks
{
    public void rWriteConsole(Rengine re, String text, int oType) {
        System.out.print(text);
    }
    public void rBusy(Rengine re, int which) {
        System.out.println("rBusy("+which+")");
    }
    public String rReadConsole(Rengine re, String prompt, int addToHistory) {
        System.out.print(prompt);
        try {
            BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
            String s=br.readLine();
            return (s==null||s.length()==0)?s:s+"\n";
        } catch (Exception e) {
            System.out.println("jriReadConsole exception: "+e.getMessage());
        }
        return null;
    }
    public void rShowMessage(Rengine re, String message) {
        System.out.println("rShowMessage \""+message+"\"");
    }
    public String rChooseFile(Rengine re, int newFile) {
    FileDialog fd = new FileDialog(new Frame(), (newFile==0)?"Select a file":"Select a new file", (newFile==0)?FileDialog.LOAD:FileDialog.SAVE);
    fd.show();
    String res=null;
    if (fd.getDirectory()!=null) res=fd.getDirectory();
    if (fd.getFile()!=null) res=(res==null)?fd.getFile():(res+fd.getFile());
    return res;
    }
    public void   rFlushConsole (Rengine re) {
    }
    public void   rLoadHistory  (Rengine re, String filename) {
    }           
    public void   rSaveHistory  (Rengine re, String filename) {
    }           
}

public class rtest {
    public static void main(String[] args) {
    // just making sure we have the right version of everything
    if (!Rengine.versionCheck()) {
        System.err.println("** Version mismatch - Java files don't match library version.");
        System.exit(1);
    }
        System.out.println("Creating Rengine (with arguments)");
        // 1) we pass the arguments from the command line
        // 2) we won't use the main loop at first, we'll start it later
        //    (that's the "false" as second argument)
        // 3) the callbacks are implemented by the TextConsole class above
        Rengine re=new Rengine(args, false, new TextConsole());
        System.out.println("Rengine created, waiting for R");
        // the engine creates R is a new thread, so we should wait until it's ready
        if (!re.waitForR()) {
            System.out.println("Cannot load R");
            return;
        }

        /* High-level API - do not use RNI methods unless there is no other way
            to accomplish what you want */
        try {
            REXP x;
            re.eval("data(iris)",false);
            System.out.println(x=re.eval("iris"));
            // generic vectors are RVector to accomodate names
            RVector v = x.asVector();
            if (v.getNames()!=null) {
                System.out.println("has names:");
                for (Enumeration e = v.getNames().elements() ; e.hasMoreElements() ;) {
                    System.out.println(e.nextElement());
                }
            }
            // for compatibility with Rserve we allow casting of vectors to lists
            RList vl = x.asList();
            String[] k = vl.keys();
            if (k!=null) {
                System.out.println("and once again from the list:");
                int i=0; while (i<k.length) System.out.println(k[i++]);
            }           

            // get boolean array
            System.out.println(x=re.eval("iris[[1]]>mean(iris[[1]])"));
            // R knows about TRUE/FALSE/NA, so we cannot use boolean[] this way
            // instead, we use int[] which is more convenient (and what R uses internally anyway)
            int[] bi = x.asIntArray();
            {
                int i = 0; while (i<bi.length) { System.out.print(bi[i]==0?"F ":(bi[i]==1?"T ":"NA ")); i++; }
                System.out.println("");
            }

            // push a boolean array
            boolean by[] = { true, false, false };
            re.assign("bool", by);
            System.out.println(x=re.eval("bool"));
            // asBool returns the first element of the array as RBool
            // (mostly useful for boolean arrays of the length 1). is should return true
            System.out.println("isTRUE? "+x.asBool().isTRUE());

            // now for a real dotted-pair list:
            System.out.println(x=re.eval("pairlist(a=1,b='foo',c=1:5)"));
            RList l = x.asList();
            if (l!=null) {
                int i=0;
                String [] a = l.keys();
                System.out.println("Keys:");
                while (i<a.length) System.out.println(a[i++]);
                System.out.println("Contents:");
                i=0;
                while (i<a.length) System.out.println(l.at(i++));
            }
            System.out.println(re.eval("sqrt(36)"));
        } catch (Exception e) {
            System.out.println("EX:"+e);
            e.printStackTrace();
        }

        // Part 2 - low-level API - for illustration purposes only!
        //System.exit(0);

        // simple assignment like a<-"hello" (env=0 means use R_GlobalEnv)
        long xp1 = re.rniPutString("hello");
        re.rniAssign("a", xp1, 0);

        // Example: how to create a named list or data.frame
        double da[] = {1.2, 2.3, 4.5};
        double db[] = {1.4, 2.6, 4.2};
        long xp3 = re.rniPutDoubleArray(da);
        long xp4 = re.rniPutDoubleArray(db);

        // now build a list (generic vector is how that's called in R)
        long la[] = {xp3, xp4};
        long xp5 = re.rniPutVector(la);

        // now let's add names
        String sa[] = {"a","b"};
        long xp2 = re.rniPutStringArray(sa);
        re.rniSetAttr(xp5, "names", xp2);

        // ok, we have a proper list now
        // we could use assign and then eval "b<-data.frame(b)", but for now let's build it by hand:       
        String rn[] = {"1", "2", "3"};
        long xp7 = re.rniPutStringArray(rn);
        re.rniSetAttr(xp5, "row.names", xp7);

        long xp6 = re.rniPutString("data.frame");
        re.rniSetAttr(xp5, "class", xp6);

        // assign the whole thing to the "b" variable
        re.rniAssign("b", xp5, 0);

        {
            System.out.println("Parsing");
            long e=re.rniParse("data(iris)", 1);
            System.out.println("Result = "+e+", running eval");
            long r=re.rniEval(e, 0);
            System.out.println("Result = "+r+", building REXP");
            REXP x=new REXP(re, r);
            System.out.println("REXP result = "+x);
        }
        {
            System.out.println("Parsing");
            long e=re.rniParse("iris", 1);
            System.out.println("Result = "+e+", running eval");
            long r=re.rniEval(e, 0);
            System.out.println("Result = "+r+", building REXP");
            REXP x=new REXP(re, r);
            System.out.println("REXP result = "+x);
        }
        {
            System.out.println("Parsing");
            long e=re.rniParse("names(iris)", 1);
            System.out.println("Result = "+e+", running eval");
            long r=re.rniEval(e, 0);
            System.out.println("Result = "+r+", building REXP");
            REXP x=new REXP(re, r);
            System.out.println("REXP result = "+x);
            String s[]=x.asStringArray();
            if (s!=null) {
                int i=0; while (i<s.length) { System.out.println("["+i+"] \""+s[i]+"\""); i++; }
            }
        }
        {
            System.out.println("Parsing");
            long e=re.rniParse("rnorm(10)", 1);
            System.out.println("Result = "+e+", running eval");
            long r=re.rniEval(e, 0);
            System.out.println("Result = "+r+", building REXP");
            REXP x=new REXP(re, r);
            System.out.println("REXP result = "+x);
            double d[]=x.asDoubleArray();
            if (d!=null) {
                int i=0; while (i<d.length) { System.out.print(((i==0)?"":", ")+d[i]); i++; }
                System.out.println("");
            }
            System.out.println("");
        }
        {
            REXP x=re.eval("1:10");
            System.out.println("REXP result = "+x);
            int d[]=x.asIntArray();
            if (d!=null) {
                int i=0; while (i<d.length) { System.out.print(((i==0)?"":", ")+d[i]); i++; }
                System.out.println("");
            }
        }

        re.eval("print(1:10/3)");

    if (true) {
        // so far we used R as a computational slave without REPL
        // now we start the loop, so the user can use the console
        System.out.println("Now the console is yours ... have fun");
        re.startMainLoop();
    } else {
        re.end();
        System.out.println("end");
    }
    }
}

控制台输出如下:

 Creating Rengine (with arguments)
Warning message:
In local({ : bytecode version mismatch; using eval
Error in objects(db.pos, all.names = TRUE) : 
  3 arguments passed to .Internal(ls) which requires 2

R version 3.0.2 (2013-09-25) -- "Frisbee Sailing"
Copyright (C) 2013 The R Foundation for Statistical Computing
Platform: x86_64-w64-mingw32/x64 (64-bit)

R is free software and comes with ABSOLUTELY NO WARRANTY.
You are welcome to redistribute it under certain conditions.
Type 'license()' or 'licence()' for distribution details.

R is a collaborative project with many contributors.
Type 'contributors()' for more information and
'citation()' on how to cite R or R packages in publications.

Type 'demo()' for some demos, 'help()' for on-line help, or
'help.start()' for an HTML browser interface to help.
Type 'q()' to quit R.

Error in .Internal(isRegisteredNamespace(name)) : 
  there is no .Internal function 'isRegisteredNamespace'
Rengine created, waiting for R
Error: could not find function "data"
Error: object 'iris' not found
null
EX:java.lang.NullPointerException
Parsing
Result = 228955128, running eval
java.lang.NullPointerExceptionError: could not find function "data"
Result = 0, building REXP

    at rtest.main(rtest.java:85)
REXP result = [NULL ]
Parsing
Result = 228997656, running eval
Error: object 'iris' not found
Result = 0, building REXP
REXP result = [NULL ]
Parsing
Result = 229003584, running eval
Error: object 'iris' not found
Result = 0, building REXP
REXP result = [NULL ]
Parsing
Result = 229018880, running eval
Error: could not find function "rnorm"
Result = 0, building REXP
REXP result = [NULL ]

REXP result = [INT* (1, 2, 3, 4, 5, 6, 7, 8, 9, 10)]
1, 2, 3, 4, 5, 6, 7, 8, 9, 10
 [1] 0.3333333 0.6666667 1.0000000 1.3333333 1.6666667 2.0000000 2.3333333
 [8] 2.6666667 3.0000000 3.3333333
Now the console is yours ... have fun
rBusy(0)
> 

在卸载现有的 R 3.0.2 并安装 R 3.2.4 并将 rjava 升级到 0.9-8 之后,一切都像魅力一样工作!!