【问题标题】:An issue when calling a Java class from R从 R 调用 Java 类时的问题
【发布时间】:2019-06-07 22:18:56
【问题描述】:

我有以下 Java 类:

public class Processor {
    public String showMsg(String msg) {
        return "The message is : " + msg;
    }

    public static void main(String [] arg) {
        Processor pro = new Processor();
        System.out.println(pro.showMsg(arg[0]));
    }
}

我想从下面的 R 脚本中调用这个类,这是我第一次使用 rJava 库:

testJav <- function(){
  library(rJava)
  .jinit()
  obj <- .jnew("/home/adam/eclipse-workspace/TestMeProject/bin/Processor.class")
  xx <- .jcall(obj,"Say hi to her") #I'm not sure if this is the right way to pass the message as a String argument!
  xx
}

当我运行脚本时,我收到以下错误:

Error in .jnew("/home/adam/eclipse-workspace/TestMeProject/bin/Processor.class") : 
  java.lang.ClassNotFoundException: /home/adam/eclipse-workspace/TestMeProject/bin/Processor/class 

虽然问题出在Processor.class,但即使我删除.class,我仍然会遇到同样的错误。

我该如何解决这个问题?

【问题讨论】:

    标签: java r classnotfoundexception rjava


    【解决方案1】:

    和你的班级一起(有一个包是个好主意)

    package mypackage;
    
    public class Processor {
        public String showMsg(String msg) {
            return "The message is : " + msg;
        }
    
        public static void main(String [] arg) {
            Processor pro = new Processor();
            System.out.println(pro.showMsg(arg[0]));
        }
    }
    

    存储在文件src/mypackage/Processor

    关注

    > mkdir target
    > javac -d target src/mypackage/Processor.java
    > export CLASSPATH=`pwd`/target
    > R
    

    然后,在 R 中,做傻事

    testJav <- function(){
      library(rJava)
      .jinit()
      obj <- .jnew("mypackage/Processor")
      xx  <- .jcall(obj, returnSig="Ljava/lang/String;", method="showMsg", "Say hi to her")
    }
    

    一切就绪后,您将获得以下内容

    > export CLASSPATH=`pwd`/target
    > R
    ...
    ...
    ...
    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.
    
    > library(rJava)
    > .jinit()
    > obj <- .jnew("mypackage/Processor")
    > xx  <- .jcall(obj, returnSig="Ljava/lang/String;", method="showMsg", "Say hi to her")
    > xx
    [1] "The message is : Say hi to her"
    >
    

    RJNI 玩得开心:)

    趣事

    您知道javap 在获取方法的签名方面非常有用吗?

    > javap -s mypackage/Processor
    Compiled from "Processor.java"
    public class mypackage.Processor {
      public mypackage.Processor();
        descriptor: ()V
    
      public java.lang.String showMsg(java.lang.String);
        descriptor: (Ljava/lang/String;)Ljava/lang/String;
    
      public static void main(java.lang.String[]);
        descriptor: ([Ljava/lang/String;)V
    }
    

    【讨论】:

    【解决方案2】:

    您正在尝试将文件路径传递给.jnew,但.jnew 没有采用文件路径。正如docs 中所述,第一个参数应该是一个

    JNI 表示法中的完全限定类名(例如“java/lang/String”)。

    基本上,如果您在 Java 程序中将您的类导入为 com.mystuff.MyClass,那么您应该传递给 .jnew 的名称将是 "com/mystuff/MyClass",而不管 .class 文件可能在哪里。

    您可能会注意到,这使您无法说出类的文件在哪里。那是因为.jnew 不是你告诉 rJava 在哪里找到东西的地方。 .jpackage 将是 R 包将其 Java 文件添加到 Java 类路径的标准方式。如果您想将任意目录或 .jar 文件添加到类路径中,还有一个 .jaddClassPath 函数。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-30
      • 2019-09-18
      相关资源
      最近更新 更多