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();
}
- 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
- 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;
}
};
g++ --std=c++17 -g -I$JAVA_HOME/include -I$JAVA_HOME/include/linux -fPIC -shared -o greetings.so Greetings.cpp
$JAVA_HOME/bin/java -Djava.library.path=/lib64 Test
同样的问题
线程中的异常 "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
。
我有一个 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();
}
- 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
- 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;
}
};
g++ --std=c++17 -g -I$JAVA_HOME/include -I$JAVA_HOME/include/linux -fPIC -shared -o greetings.so Greetings.cpp
$JAVA_HOME/bin/java -Djava.library.path=/lib64 Test
同样的问题
线程中的异常 "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
。