java - 将SmartID Reader JNI库添加到现有的gradle项目中

标签 java gradle java-native-interface

我正在尝试在我现有的 Gradle 项目中使用 Smart IDReader SDK 试用版 ( https://habr.com/en/company/smartengines/blog/332670/ )(项目组装到 war-archive 中)。 应用程序工作站是centOS,我不需要支持 native 库的所有架构。所以,我有 libjniSmartIdEngine.so native 库和 jniSmartIdEngineJar.jar。 SDK 中还提供了 c++ *.h 文件和 *java SWIG 类。 我正在尝试:

  1. 在/resources/中添加jar和so库。
  2. 在 build.gradle 依赖项中添加编译文件('lib/jniSmartIdEngineJar.jar', 'libjniSmartIdEngine.so')。
  3. 在我想要使用提供的示例代码的类中的静态 block 中加载资源。

    静态{ URL jniWrapper = SmartIDReader.class.getResource("/res/jniSmartIdEngineJar.jar"); System.load(jniWrapper.getPath()); }

Jar 和 So 放在同一文件夹中,但出现错误:

It's highly recommended that you fix the library with 'execstack -c <libfile>', or link it with '-z noexecstack'.Exception in thread "main" java.lang.UnsatisfiedLinkError: /jniSmartIdEngineJar.jar: /jniSmartIdEngineJar.jar: invalid ELF header (Possible cause: endianness mismatch)
at java.lang.ClassLoader$NativeLibrary.load(Native Method)
at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1941)
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1824)
at java.lang.Runtime.load0(Runtime.java:809)
at java.lang.System.load(System.java:1086)

我需要的一切 - 这是在我的项目中正确初始化库,但我不明白如何初始化。 我找到了一些解决方案: * Correct way to add external jars (lib/*.jar) to an IntelliJ IDEA project建议在项目结构中手动添加依赖项(但是当我像上面描述的那样通过 gradle 添加它时,库已经存在)/ * How to bundle a native library and a JNI library inside a JAR?这里建议使用 jar,而不是 war 。如果我理解正确,我不需要将库解压到临时文件并加载它。

这是库的运行程序:

javac *.java -cp ../../bindings/java/jniSmartIdEngineJar.jar

for image in ../../testdata/*; do 
  config=$(ls ../../data-zip/*.zip) # assuming one file
  for document_types in "rus.passport.*" "mrz.*" "rus.drvlic.*" "*"; do
    LD_LIBRARY_PATH=../../bin LC_ALL=en_US.utf-8 java -cp ../../bindings/java/jniSmartIdEngineJar.jar:. Main "$image" "$config" "$document_types"
  done
done

请解释一下如何在我的项目中使用外部 JNI 库。以及如何用 gradle 配置替换该 shell 运行程序。

PS.:我正在 Ubuntu 上工作,并且 shell 运行程序工作正常。我做错了什么?

最佳答案

找到解决方案:

  1. 要加载外部 JNI 库,必须将其添加到项目文件夹中(例如/lib/)
  2. JAR 包装文件(在我的例子中生成的 swig)必须添加为依赖项(右键单击 jar > 添加为库或在项目结构模块依赖项中手动添加)。就我而言,我使用的是 gradle

        compile fileTree(include: ['*.jar'], dir: 'lib')
    

    在依赖项{} block 中

  3. 之后,jar 中的类将在项目中可用,以及我们需要的所有内容 - 添加 native 库。有几种方法:设置 -Djava.library.path=... 作为 JVM 运行参数,或者像下面描述的那样动态配置它: https://habr.com/en/post/118027/ 另一种方法 - 只需将库放在系统文件夹中或在系统变量中添加新目录(Windows 上的路径或 Linux 上的 LD_LIBRARY_PATH)。此处说明:How should I load native libraries for JNI to avoid an UnsatisfiedLinkError?

关于 shell 脚本:在 p.1 中,我们在类路径中添加了 jar-wrapper 必须指定 Linux 的 LD_LIBRARY_PATH 或其他描述的解决方案,其中 jvm 将能够找到 native 库。

最后 - SmartId Reader 没有 ubuntu sdk,因此 centOS 软件包无法在 ubuntu 上运行(jvm SIGSEGV 错误,有问题的框架:ld-linux-x86-64.so)。我只是使用 Windows sdk,它解决了问题。

关于java - 将SmartID Reader JNI库添加到现有的gradle项目中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60402296/

相关文章:

android - 编译Android应用程序时出现问题,依赖项

java - Linux Java : load . 如此动态,无需 dlopen

java - 如何使用JNI获取AD用户的属性?

java - 为什么 java -version 返回旧版本?

java - 查找字符串的超字符串的最快数据结构?

java - 在 List 的每个索引上创建 ArrayList

gradle - Gradle 不满足依赖关系?

android - 从 .gradle 脚本打印消息到 Gradle Sync 日志

java - 使用配置文件设置 Java 系统属性

java - 将 JMSListener 与 RabbitMQ 结合使用