Hadi
Hadi

Reputation: 995

Building .so file with JNI issue

I have the exact same code as Trouble with compiling JNI. In fact, had the same issue. Tried solving using the two step approach, which is running the following:

cc -c HelloWorld.c

Then the next command:

cc -shared -o libHelloWorld.so HelloWorld.o

The first one runs find and creates HelloWorld.o, however, after running the second command, I get this error:

/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

I'm running an ubuntu 16.04 and JDK version 8

Any ideas?

Upvotes: 0

Views: 1300

Answers (1)

Oo.oO
Oo.oO

Reputation: 13375

If you start your experience with JNI, it's always good to start with super simple - preferably "Hello world" - sample. This way, you can make sure all the elements in the chain are working as expected.

Start with simple class (it's good idea to put it inside package):

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();
  }
}

You will also need native code itself. Make it as simple as possible

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

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

  printf("Hello world!\n");

}

Note that JNI has a fixed naming convention when it comes to names of the functions: Resolving Native Method Names

Then, you can compile everything:

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

-d means that classes will be compiled inside directory target

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

Once everything is compiled, you can simply run the sample:

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

Note that we are setting class path with -cp because class files were generated inside target directory.

That's it :) You can find more samples here: JNI Cookbook

Upvotes: 1

Related Questions