使用JNI问题构建.so文件

时间:2018-02-01 23:45:14

标签: java c++ c linux java-native-interface

我的代码与Trouble with compiling JNI完全相同。事实上,有同样的问题。尝试使用两步法解决问题,该方法运行如下:

cc -c HelloWorld.c

然后是下一个命令:

cc -shared -o libHelloWorld.so HelloWorld.o

第一个运行find并创建HelloWorld.o,但是,在运行第二个命令后,我收到此错误:

/usr/bin/ld: /tmp/ccA9BIT2.o: relocation R_X86_64_32 against `.rodata' can not be used when making a shared object; recompile with -fPIC /tmp/ccA9BIT2.o: error adding symbols: Bad value collect2: error: ld returned 1 exit status

我正在运行ubuntu 16.04和JDK版本8

有什么想法吗?

1 个答案:

答案 0 :(得分:1)

如果您开始使用JNI,那么从超简单开始总是好的 - 最好是“Hello world” - 样本。这样,您可以确保链中的所有元素都按预期工作。

从简单的类开始(最好把它放在包中):

package recipeNo001;

public class HelloWorld {

  /* This is the native method we want to call */
  public static native void displayMessage();

  /* Inside static block we will load shared library */
  static {
    System.loadLibrary("HelloWorld");
  }

  public static void main(String[] args) {
    /* Call to shared library */
    HelloWorld.displayMessage();
  }
}

您还需要本机代码。尽可能简单

#include <stdio.h>
#include "jni.h"

JNIEXPORT void JNICALL Java_recipeNo001_HelloWorld_displayMessage
  (JNIEnv *env, jclass obj) {

  printf("Hello world!\n");

}

请注意,JNI在函数名称方面有一个固定的命名约定:Resolving Native Method Names

然后,您可以编译所有内容:

${JAVA_HOME}/bin/javac -d target java/recipeNo001/HelloWorld.java

-d表示将在目录target

中编译类
cc -g -shared -fpic -I${JAVA_HOME}/include \ 
  -I${JAVA_HOME}/include/$(ARCH) HelloWorld.c \
  -o lib/libHelloWorld.so

编译完所有内容后,您只需运行示例:

${JAVA_HOME}/bin/java \
  -Djava.library.path=${LD_LIBRARY_PATH}:./lib \
  -cp target recipeNo001.HelloWorld

请注意,我们使用-cp设置类路径,因为类文件是在target目录中生成的。

就是这样:)你可以在这里找到更多样本:JNI Cookbook