centos7 上未调用 JNI 方法

JNI method not invoked on centos7

我有一个 Java 代码 ServiceTest.java 调用 JNI 代码 buildCache() 来构建缓存。此代码在 Ubuntu 上正确编译和执行;然而,在centos上我编译并执行并得到了这个错误。

Exception in thread "main" java.lang.UnsatisfiedLinkError: com.test.app.ServiceTest.buildCache()V
    at com.test.app.ServiceTest.buildCache(Native Method)
    at com.test.app.ServiceTest.<init>(ServiceTest.java:15)
    at com.test.app.ServiceTest.main(ServiceTest.java:47)

貌似可以加载so文件,但是调用不了方法

ServiceTest.java

public class ServiceTest{


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

 public ServiceTest() {
        buildCache();
    }

 private native void buildCache();
}

libcacheService.so放在/usr/local/lib64中。我有 gcc 9 和 jdk 1.8 并设置 LD_LIBRARY_PATH=/usr/local/ 并导出 $LD_LIBRARY_PATH。

知道如何调试吗?


              ******Adding below simple testcode****** 

1.

public class Test{


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

    Test(){
    }

    public static void main(String...s){
      Test t = new Test();
      System.out.println(t.greetings());
    }
    private native String greetings();
}
  1. javah 测试 -> Test.h
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h> /* Header for class Test */

#ifndef _Included_Test
#define _Included_Test
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     Test
 * Method:    greetings
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_Test_greetings
(JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif
  1. Greetings.cpp
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <jni.h>
#include "Test.h"
using namespace std;

class Test{

JNIEXPORT jstring JNICALL Java_Test_greetings(JNIEnv *env, jobject thisObject){
   jstring result = env->NewStringUTF("hi from JNI"); 
   return result;
 }  

};
  1. g++ --std=c++17 -g -I$JAVA_HOME/include -I$JAVA_HOME/include/linux -fPIC -shared -o greetings.so Greetings.cpp

  2. $JAVA_HOME/bin/java -Djava.library.path=/lib64 Test

  3. 同样的问题

线程中的异常 "main" java.lang.UnsatisfiedLinkError: Test.greetings()Ljava/lang/String; 在 Test.greetings(本机方法) 在 Test.main(Test.java:13)

使用相同的 GCC 9 和 jdk1.8

问题是原生库没有定义匹配Java native方法签名的方法;即 JNI 代码中的方法名称或签名错误......或者它可能根本不是 JNI 本机库。

您的 Greetings.cpp 不应该包括 class Test:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <jni.h>
#include "Test.h"
using namespace std;

JNIEXPORT jstring JNICALL Java_Test_greetings(JNIEnv *env, jobject thisObject){
   jstring result = env->NewStringUTF("hi from JNI"); 
   return result;
 }  

那么,Java语句System.loadLibrary("greet");期望在其java.library.path中找到一个libgreet.so,所以编译如下:

g++ --std=c++17 -g -I$JAVA_HOME/include -I$JAVA_HOME/include/linux -fPIC -shared -o libgreet.so Greetings.cpp

接下来,验证符号的命名是否与函数完全相同,即 nm libgreet.so | grep Java_Test_greetings 应该产生如下输出:

0000000000000f20 T _Java_Test_greetings

最后,运行 您的 Java 程序具有正确的 java.library.path