将 JNI 库添加到 Spring Boot (maven) jar

问题描述 投票:0回答:3

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

  1. 安装 Microsoft Visual C++ Redistributable for Visual Studio 2019(根据安装说明需要)。

  2. 下载并解压适用于 Java 的 OR-Tools 库(包括 2 个 jar 和 1 个 dll 文件)。

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

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

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

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

现在我可以从 Intellij 成功运行该项目了。 接下来,我想将所有内容打包到一个可以在任何 Windows 机器上运行的 Spring Boot jar 中。

我的文件夹结构是:

enter image description here

我的 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 将这些第 3 方 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
3个回答
0
投票

我尝试过:

首先务实地将

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>

0
投票

任何人都可以给我确切的下载链接,并说明我在哪里可以获得 64 位 os-64 位系统的 .dll 文件(使用 gradle 的 springboot 项目)


-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>

但是,这种方法也可能很痛苦,尤其是当您必须在多平台上工作时。最近,我发现了这个存储库,这让我使用 OR 工具的生活变得更加轻松。希望这有帮助。

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

<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,如此处所述。

© www.soinside.com 2019 - 2024. All rights reserved.