【问题标题】:Adding a JNI library to a spring boot (maven) jar将 JNI 库添加到 spring boot (maven) jar
【发布时间】:2020-10-18 12:51:55
【问题描述】:

我在 Java-Spring-Boot 应用、Windows 10 操作系统和 Intellij IDE 上使用 Google Or-Tools 库。 为了让它在 intellij 上运行,我做了以下操作:

  1. 为 Visual Studio 2019 安装 Microsoft Visual C++ Redistributable(根据installation instructions 要求)。

  2. 下载并提取 Java 的 OR-Tools 库(包括 2 个 jar 和 1 个 dll 文件)。

  3. 在 Intellij 中,我将这些 jars 添加为模块依赖项(在名为 lib 的文件夹下)。

  4. 将 lib 库路径添加到 Intellij 运行配置中的 VM 选项。

  5. 在我的代码中静态加载库:

    static {System.loadLibrary("jniortools");}

现在我可以从 Intellij 成功运行项目。 接下来我想把所有东西打包到一个可以在任何windows机器上运行的spring boot jar中。

我的文件夹结构是:

我的 pom 文件非常基础,一些依赖于标准 spring-boot-maven-plugin:

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>

当我尝试使用 mvn install 打包代码时,我得到了包 com.google.ortools.sat does not exist

如何确保 maven 将这些 3rd 方 jar 打包到可执行的 spring-boot jar 中?

更新

我添加到我的 pom 文件中:

<dependency>
    <groupId>com.google.ortools</groupId>
    <artifactId>ortools</artifactId>
    <version>LATEST</version>
    <type>jar</type>
    <scope>system</scope>
    <systemPath>${project.basedir}/lib/com.google.ortools.jar</systemPath>
</dependency>
<dependency>
    <groupId>com.google.protobuf</groupId>
    <artifactId>protobuf-java</artifactId>
    <version>LATEST</version>
    <type>jar</type>
    <scope>system</scope>
    <systemPath>${project.basedir}/lib/protobuf.jar</systemPath>
</dependency>


<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-antrun-plugin</artifactId>
            <version>1.7</version>
            <executions>
                <execution>
                    <phase>generate-test-sources</phase>
                    <configuration>
                        <tasks>
                            <mkdir dir="${project.basedir}/target/lib"/>
                            <echo message="Creating lib folder..."/>
                            <copy todir="${project.basedir}/target/lib">
                                <fileset dir="${project.basedir}/lib">
                                    <include name="**/**"/>
                                </fileset>
                            </copy>
                        </tasks>
                    </configuration>
                    <goals>
                        <goal>run</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>

除了添加到库路径:

static {
    try {
        String orToolsDllLibrary = System.getProperty("user.dir") + "\\lib";
        addLibraryPath(orToolsDllLibrary);
        System.loadLibrary("jniortools");
    } catch (Exception e) {
        e.printStackTrace();
    }
}

public static void addLibraryPath(String pathToAdd) throws Exception {
    final Field usrPathsField = ClassLoader.class.getDeclaredField("usr_paths");
    usrPathsField.setAccessible(true);

    //get array of paths
    final String[] paths = (String[]) usrPathsField.get(null);

    //check if the path to add is already present
    for (String path : paths) {
        if (path.equals(pathToAdd)) {
            return;
        }
    }

    //add the new path
    final String[] newPaths = Arrays.copyOf(paths, paths.length + 1);
    newPaths[newPaths.length - 1] = pathToAdd;
    usrPathsField.set(null, newPaths);
}

现在在运行命令 java -jar myApp-0.0.1-SNAPSHOT.jar 时出现异常:

Caused by: java.lang.NoClassDefFoundError: com/google/ortools/sat/CpSolver
        at java.base/java.lang.Class.getDeclaredMethods0(Native Method) ~[na:na]
        at java.base/java.lang.Class.privateGetDeclaredMethods(Class.java:3167) ~[na:na]
        at java.base/java.lang.Class.getDeclaredMethods(Class.java:2310) ~[na:na]
        at org.springframework.util.ReflectionUtils.getDeclaredMethods(ReflectionUtils.java:463) ~[spring-core-5.2.6.RELEASE.jar!/:5.2.6.RELEASE]
        ... 29 common frames omitted
Caused by: java.lang.ClassNotFoundException: com.google.ortools.sat.CpSolver
        at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:471) ~[na:na]
        at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:588) ~[na:na]
        at org.springframework.boot.loader.LaunchedURLClassLoader.loadClass(LaunchedURLClassLoader.java:129) ~[solver-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
        at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521) ~[na:na]
        ... 33 common frames omitted

【问题讨论】:

    标签: maven maven-assembly-plugin or-tools spring-boot-maven-plugin


    【解决方案1】:

    我不确定您是如何将库添加到您的项目中的?您似乎不是通过 Maven 完成的,对吗?

    过去我采用在 Maven 中使用 system 作用域添加它的方法(请参阅 here。这会在你的 pom 中给你这样的东西:

    <dependency>
        <groupId>com.google.ortools</groupId>
        <artifactId>ortools</artifactId>
        <version>1.0</version>
        <scope>system</scope>
        <systemPath>${basedir}/src/main/resources/lib/com.google.ortools.jar</systemPath>
    </dependency>
    

    但是,这种方法也可能很痛苦,尤其是在您必须在多平台工作时。最近,我找到了this repo,这让我在处理 OR-tools 时变得更加轻松。希望这会有所帮助。

    更新: 我强烈建议使用下面的更新方法,因为它不那么令人头疼:

    <repositories>
        ...
        <repository>
            <id>bintray</id>
            <url>https://dl.bintray.com/magneticflux/maven</url>
        </repository>
        ....
    </repositories>
    
    <dependencies>
      <dependency>
           <groupId>com.skaggsm.ortools</groupId>
           <artifactId>ortools-natives-all</artifactId>
           <version>7.7.7810</version>
      </dependency>
      <!-- OR-tools needs protobuf       -->
       <dependency>
           <groupId>com.google.protobuf</groupId>
           <artifactId>protobuf-java</artifactId>
           <version>3.12.2</version>
       </dependency>
    </dependencies>
    

    然后你可以做一个库的静态加载:

    static {
        OrToolsHelper.loadLibrary()
    }
    

    确保使用 JDK >= 11,如 here 所述。

    【讨论】:

    • 这个 repo 看起来很有希望,我会尽快尝试
    • 仍然无法正常工作。我刚刚更新了问题,您可以看看吗?
    • 确实有效!我不得不将 protobuf 版本更改为 3.12.2,并将我的 java 版本更新为 14。
    【解决方案2】:

    我试过了:

    首先务实地将jniortools库添加到java.library.path

    static {
        String orToolsDllLibrary = System.getProperty("user.dir") + "\\lib";
        addLibraryPath(orToolsDllLibrary);
        System.loadLibrary("jniortools");
    }
    
    
    public static void addLibraryPath(String pathToAdd) throws Exception {
        final Field usrPathsField = ClassLoader.class.getDeclaredField("usr_paths");
        usrPathsField.setAccessible(true);
    
        //get array of paths
        final String[] paths = (String[]) usrPathsField.get(null);
    
        //check if the path to add is already present
        for (String path : paths) {
            if (path.equals(pathToAdd)) {
                return;
            }
        }
    
        //add the new path
        final String[] newPaths = Arrays.copyOf(paths, paths.length + 1);
        newPaths[newPaths.length - 1] = pathToAdd;
        usrPathsField.set(null, newPaths);
    }
    

    在 pom 文件中:

    <dependencies>
    ....
    
        <dependency>
            <groupId>com.google.protobuf</groupId>
            <artifactId>protobuf-java</artifactId>
            <version>3.12.2</version>
        </dependency>
        <dependency>
            <groupId>com.google</groupId>
            <artifactId>ortools</artifactId>
            <version>0.0.2</version>
        </dependency>
        
        ....
    </dependencies>
    
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-install-plugin</artifactId>
                <version>2.5.2</version>
                <executions>
                    <execution>
                        <id>install-external</id>
                        <phase>process-resources</phase>
                        <configuration>
                            <file>${basedir}/lib/com.google.ortools.jar</file>
                            <repositoryLayout>default</repositoryLayout>
                            <groupId>com.google</groupId>
                            <artifactId>ortools</artifactId>
                            <version>0.0.2</version>
                            <packaging>jar</packaging>
                            <generatePom>true</generatePom>
                        </configuration>
                        <goals>
                            <goal>install-file</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-antrun-plugin</artifactId>
                <version>1.7</version>
                <executions>
                    <execution>
                        <phase>generate-sources</phase>
                        <configuration>
                            <tasks>
                                <mkdir dir="${project.basedir}/target/lib"/>
                                <echo message="Creating lib folder..."/>
                                <copy todir="${project.basedir}/target/lib">
                                    <fileset dir="${project.basedir}/lib">
                                        <include name="**/**"/>
                                    </fileset>
                                </copy>
                            </tasks>
                        </configuration>
                        <goals>
                            <goal>run</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-02-10
      • 2012-08-13
      • 1970-01-01
      • 2018-01-31
      • 1970-01-01
      • 2014-04-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多