运行使用Maven构建的jar会导致“java.lang”。NoClassDefFoundError:org/rosuda/JRI/Rengine”错误

时间:2023-01-25 23:37:28

I am trying to build a JAR library that can invoke R code. I basically want this jar to be capable enough to be able to run on any machine that has support for running jar executables(No need of seperate R software). For this I am using Maven. I am able to compile and create a jar without any errors. However, when I run it, I am unable to yield successful results.

我正在尝试构建一个JAR库,它可以调用R代码。我基本上希望这个jar能够在任何支持运行jar可执行程序的机器上运行(不需要seperate R软件)。为此,我使用Maven。我能够编译并创建一个jar,没有任何错误。然而,当我运行它时,我无法产生成功的结果。

This is my java code

这是我的java代码

package com.company.analytics.timeseries;

import org.rosuda.JRI.REXP;
import org.rosuda.JRI.Rengine;

public class App {
    public static void main(String[] args) {
        System.out.println("Creating Rengine (with arguments)");
        String[] Rargs = { "--vanilla" };
        Rengine re = new Rengine(Rargs, false, null);
        System.out.println("Rengine created, waiting for R");
        if (!re.waitForR()) {
            System.out.println("Cannot load R");
            return;
        }
        System.out.println("Done.");
    }
}

This is my pom.xml file

这是我的砰的一声。xml文件

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.company.analytics</groupId>
  <artifactId>timeseries</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>timeseries</name>
  <url>http://maven.apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.nuiton.thirdparty</groupId>
      <artifactId>JRI</artifactId>
      <version>RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.rosuda.REngine</groupId>
      <artifactId>REngine</artifactId>
      <version>2.1.0</version>
    </dependency>
  </dependencies>

  <repositories>
    <repository>
      <id>central</id>
      <name>Maven Central</name>
      <url>http://repo1.maven.org/maven2</url>
    </repository>
  </repositories>

</project>

I used mvn clean and then mvn package to create the jar file.

我使用mvn clean,然后使用mvn包创建jar文件。

A JAR file of 4KB is created in C:\MVN\project\analytics\timeseries\target. Thern, from the command line on Windows, when I run execute this jar file, I get the following error

一个4KB的JAR文件是在C:\MVN\项目\分析\timeseries\target中创建的。在Windows上的命令行中,当我运行这个jar文件时,会得到以下错误

C:\MVN\project\analytics\timeseries\target\classes>java com.company.analytics.timeseries.App

Creating Rengine (with arguments)

Exception in thread "main" java.lang.NoClassDefFoundError: org/rosuda/JRI/Rengine

    at com.company.analytics.timeseries.App.main(App.java:10)
Caused by: java.lang.ClassNotFoundException: org.rosuda.JRI.Rengine
        at java.net.URLClassLoader.findClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        ... 1 more

I am trying to figure out what mistake am I committing. I tried to find answers by googling, but I couldn't fix it.

我在想我犯了什么错误。我试着用谷歌搜索来寻找答案,但我没能解决它。

3 个解决方案

#1


4  

Since I've been smashing my head against this for a day now and I'll likely forget in the future and reference this page - per what Gergely Basco's suggests in an above comment, strictly speaking both R and rJava need to be installed on the machine in order to resolve the Cannot find JRI native library! issue when instantiating your org.rosuda.REngine.REngine object, and this cannot be done exclusively by way of adding the JRIEngine dependency in your pom.xml (bummer).

以来我一直对这砸我的头一天,我可能会忘记在未来和参考这个页面——每Gergely正在显示在一个以上的评论,严格说来R和rJava需要安装的机器上,以解决无法找到JRI本地库!实例化您的org.rosuda.REngine时发出。REngine对象,这不能通过在pom中添加JRIEngine依赖项来完成。xml(游手好闲的人)。

Steps (for how I'm doing it anyway for my later image):

步骤(对于我以后的图片来说):

  1. Install Brew (I just happen to be using Brew for other dependencies)

    安装Brew(我只是碰巧使用Brew作其他依赖)

     /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
    
  2. Install R using brew:

    安装使用酿造R:

    brew tap homebrew/science
    brew install R
    
  3. Install rJava with R (takes a bit of compile time, grab a coffee)

    用R安装rJava(需要一点编译时间,喝杯咖啡)

    install.packages("rJava")
    
  4. add rJava/jri to java.library.path classpath, add R_HOME to environment variables (where you installed R - in my case, where Brew installed it). Note that if you're trying to run this in your IDE(I'm running IDEA16), it won't inherit the path you set in ~/.bash_profile, you need to set it in your run configuration.

    添加rJava / jri java.library。路径类路径,将R_HOME添加到环境变量中(在我的例子中,在Brew中安装了R)。注意,如果您试图在IDE中运行这个(我正在运行IDEA16),它不会继承您在~/中设置的路径。bash_profile需要在运行配置中设置。

     -Djava.library.path="/usr/local/lib/R/3.3/site-library/rJava/jri/
     R_HOME=/usr/local/Cellar/r/3.3.1_2/R.framework/Resources
    
  5. Ensure maven has dependency for JRIEngine in pom.xml

    确保maven对JRIEngine有依赖性。

    <dependency>
        <groupId>com.github.lucarosellini.rJava</groupId>
        <artifactId>JRIEngine</artifactId>
        <version>0.9-7</version>
    </dependency>
    
  6. Instantiate REngine (I need this version in order to pass dataframe to R from java)

    实例化REngine(我需要这个版本,以便从java将dataframe传递给R)

    String[] Args = {"--vanilla"};
    REngine engine = REngine.engineForClass("org.rosuda.REngine.JRI.JRIEngine", Args, new REngineStdOutput (), false);
    

What you should end up with looks something like this at runtime, if you instantiate with the callback argument (new REngineStdOutput () ); otherwise if you just instantiate with the String engineForClass("org.rosuda.REngine.JRI.JRIEngine"), you'll wont get the below output from R on startup/elsewise, depending on if you want it or not:

如果使用回调参数实例化(新的REngineStdOutput())),那么在运行时应该得到的结果是这样的;否则,如果您只是使用String engineForClass(“org.rosuda. rengine.jriengine . jriengine”)进行实例化,那么在启动/其他情况下,您将无法从R获得以下输出,这取决于您是否需要:

    /**R version 3.3.1 (2016-06-21) -- "Bug in Your Hair"
    Copyright (C) 2016 The R Foundation for Statistical Computing
    Platform: x86_64-apple-darwin15.5.0 (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.

      Natural language support but running in an English locale

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

Hope this helps someone in the future and saves them from the pain.

希望这能帮助未来的人,让他们免受痛苦。

#2


1  

You need to build a jar with all your dependencies included. (aka fat jar) Since you are already using Maven, the only thing you need to do is to instruct Maven to include the dependencies by adding this plugin to your pom.xml file:

您需要构建一个包含所有依赖项的jar。既然您已经在使用Maven,那么惟一需要做的就是通过将这个插件添加到pom中来指示Maven包含依赖项。xml文件:

<build>
   <plugins>
      <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-assembly-plugin</artifactId>
            <version>2.5.5</version>
            <configuration>
                <descriptorRefs>
                    <descriptorRef>jar-with-dependencies</descriptorRef>
                </descriptorRefs>
            </configuration>
            <executions>
                <execution>
                    <id>assemble-all</id>
                    <phase>package</phase>
                    <goals>
                        <goal>single</goal>
                    </goals>
                </execution>
            </executions>
      </plugin>
   </plugins>
</build>

#3


0  

You are missing the classpath argument. Your jar file contains your compiled code without any 3rd party jars. When you want to run it, you should add -cp and point to all your 3rd party jars.

您丢失了类路径参数。您的jar文件包含编译后的代码,没有任何第三方jar。当您想要运行它时,您应该添加-cp并指向所有的第三方jar。

You can also build a single jar with all dependencies using Maven's assembly plugin.

您还可以使用Maven的assembly插件构建一个包含所有依赖项的jar。

#1


4  

Since I've been smashing my head against this for a day now and I'll likely forget in the future and reference this page - per what Gergely Basco's suggests in an above comment, strictly speaking both R and rJava need to be installed on the machine in order to resolve the Cannot find JRI native library! issue when instantiating your org.rosuda.REngine.REngine object, and this cannot be done exclusively by way of adding the JRIEngine dependency in your pom.xml (bummer).

以来我一直对这砸我的头一天,我可能会忘记在未来和参考这个页面——每Gergely正在显示在一个以上的评论,严格说来R和rJava需要安装的机器上,以解决无法找到JRI本地库!实例化您的org.rosuda.REngine时发出。REngine对象,这不能通过在pom中添加JRIEngine依赖项来完成。xml(游手好闲的人)。

Steps (for how I'm doing it anyway for my later image):

步骤(对于我以后的图片来说):

  1. Install Brew (I just happen to be using Brew for other dependencies)

    安装Brew(我只是碰巧使用Brew作其他依赖)

     /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
    
  2. Install R using brew:

    安装使用酿造R:

    brew tap homebrew/science
    brew install R
    
  3. Install rJava with R (takes a bit of compile time, grab a coffee)

    用R安装rJava(需要一点编译时间,喝杯咖啡)

    install.packages("rJava")
    
  4. add rJava/jri to java.library.path classpath, add R_HOME to environment variables (where you installed R - in my case, where Brew installed it). Note that if you're trying to run this in your IDE(I'm running IDEA16), it won't inherit the path you set in ~/.bash_profile, you need to set it in your run configuration.

    添加rJava / jri java.library。路径类路径,将R_HOME添加到环境变量中(在我的例子中,在Brew中安装了R)。注意,如果您试图在IDE中运行这个(我正在运行IDEA16),它不会继承您在~/中设置的路径。bash_profile需要在运行配置中设置。

     -Djava.library.path="/usr/local/lib/R/3.3/site-library/rJava/jri/
     R_HOME=/usr/local/Cellar/r/3.3.1_2/R.framework/Resources
    
  5. Ensure maven has dependency for JRIEngine in pom.xml

    确保maven对JRIEngine有依赖性。

    <dependency>
        <groupId>com.github.lucarosellini.rJava</groupId>
        <artifactId>JRIEngine</artifactId>
        <version>0.9-7</version>
    </dependency>
    
  6. Instantiate REngine (I need this version in order to pass dataframe to R from java)

    实例化REngine(我需要这个版本,以便从java将dataframe传递给R)

    String[] Args = {"--vanilla"};
    REngine engine = REngine.engineForClass("org.rosuda.REngine.JRI.JRIEngine", Args, new REngineStdOutput (), false);
    

What you should end up with looks something like this at runtime, if you instantiate with the callback argument (new REngineStdOutput () ); otherwise if you just instantiate with the String engineForClass("org.rosuda.REngine.JRI.JRIEngine"), you'll wont get the below output from R on startup/elsewise, depending on if you want it or not:

如果使用回调参数实例化(新的REngineStdOutput())),那么在运行时应该得到的结果是这样的;否则,如果您只是使用String engineForClass(“org.rosuda. rengine.jriengine . jriengine”)进行实例化,那么在启动/其他情况下,您将无法从R获得以下输出,这取决于您是否需要:

    /**R version 3.3.1 (2016-06-21) -- "Bug in Your Hair"
    Copyright (C) 2016 The R Foundation for Statistical Computing
    Platform: x86_64-apple-darwin15.5.0 (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.

      Natural language support but running in an English locale

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

Hope this helps someone in the future and saves them from the pain.

希望这能帮助未来的人,让他们免受痛苦。

#2


1  

You need to build a jar with all your dependencies included. (aka fat jar) Since you are already using Maven, the only thing you need to do is to instruct Maven to include the dependencies by adding this plugin to your pom.xml file:

您需要构建一个包含所有依赖项的jar。既然您已经在使用Maven,那么惟一需要做的就是通过将这个插件添加到pom中来指示Maven包含依赖项。xml文件:

<build>
   <plugins>
      <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-assembly-plugin</artifactId>
            <version>2.5.5</version>
            <configuration>
                <descriptorRefs>
                    <descriptorRef>jar-with-dependencies</descriptorRef>
                </descriptorRefs>
            </configuration>
            <executions>
                <execution>
                    <id>assemble-all</id>
                    <phase>package</phase>
                    <goals>
                        <goal>single</goal>
                    </goals>
                </execution>
            </executions>
      </plugin>
   </plugins>
</build>

#3


0  

You are missing the classpath argument. Your jar file contains your compiled code without any 3rd party jars. When you want to run it, you should add -cp and point to all your 3rd party jars.

您丢失了类路径参数。您的jar文件包含编译后的代码,没有任何第三方jar。当您想要运行它时,您应该添加-cp并指向所有的第三方jar。

You can also build a single jar with all dependencies using Maven's assembly plugin.

您还可以使用Maven的assembly插件构建一个包含所有依赖项的jar。