Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?

JNI Example (Mac OS)

JNI (Java Native Interface) allows implementing methods in C/C++, and use them in Java.

1. Create JNIExample.java file

class JNIExample {

  // Native method, no body.
  public native void sayHello(int length);

  public static void main (String args[]) {
    String str = "Hello, world!";

    (new JNIExample()).sayHello(str.length());
  }

  // This loads the library at runtime. NOTICE: on *nix/Mac the extension of the
  // lib should exactly be `.jnilib`, not `.so`, and have `lib` prefix, i.e.
  // the library file should be `libjniexample.jnilib`.
  static {
    System.loadLibrary("jniexample");
  }
}

2. Compile the JNIExample.java file

This gives you JNIExample.class:

javac JNIExample.java

3. Codegen .h file for JNI

javah -jni JNIExample

This gives you JNIExample.h (do not edit it manually!):

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class JNIExample */

#ifndef _Included_JNIExample
#define _Included_JNIExample
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     JNIExample
 * Method:    sayHello
 * Signature: (I)V
 */
JNIEXPORT void JNICALL Java_JNIExample_sayHello
  (JNIEnv *, jobject, jint);

#ifdef __cplusplus
}
#endif
#endif

4. Create JNIExample.c

Native implementation:

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

JNIEXPORT void JNICALL Java_JNIExample_sayHello
  (JNIEnv *env, jobject object, jint len) {
  printf("\nThe length of your string is %d.\n\n", len);
}

5. Compile C library

IMPORTANT: library extension should exactly be .jnilib (not .so!), and should have lib prefix, i.e. libjniexample.jnilib:

gcc -I"$JAVA_HOME/include" -I"$JAVA_HOME/include/darwin/" -o libjniexample.jnilib -shared JNIExample.c

NOTICE: the $JAVA_HOME can be taken from (for 1.8 version in this case):

export JAVA_HOME="$(/usr/libexec/java_home -v 1.8)"

6. Execute the java class

Notice, we set java.library.path to current directory, where the libjniexample.jnilib was compiled to:

java -Djava.library.path=. JNIExample

Result:

The length of your string is 13.
@anggara-kaskus

This comment has been minimized.

Copy link

@anggara-kaskus anggara-kaskus commented Feb 18, 2021

I got error when generating header (I use JDK 11)

$ javah -jni JNIExample
Unable to locate an executable at "/Library/Java/JavaVirtualMachines/jdk-11.0.5.jdk/Contents/Home/bin/javah" (-1)

It is because javah is removed in Java 10.
As replacement, I can run this successfully:

$ javac JNIExample.java -h .
@yemistar

This comment has been minimized.

Copy link

@yemistar yemistar commented Apr 1, 2021

Hello, When I run the command:
gcc -I"$JAVA_HOME/include" -I"$JAVA_HOME/include/darwin/" -o libjniexample.jnilib -shared JNIExample.c
i get the error:

JNIExample.c:2:10: fatal error: 'jni.h' file not found #include <jni.h> ^~~~~~~ 1 error generated.

Do yo know how to solve this error? I am using macOS big sur 11.2.3

@zzhou37

This comment has been minimized.

Copy link

@zzhou37 zzhou37 commented Aug 17, 2021

Hello, When I run the command:
gcc -I"$JAVA_HOME/include" -I"$JAVA_HOME/include/darwin/" -o libjniexample.jnilib -shared JNIExample.c
i get the error:

JNIExample.c:2:10: fatal error: 'jni.h' file not found #include <jni.h> ^~~~~~~ 1 error generated.

Do yo know how to solve this error? I am using macOS big sur 11.2.3

I had the same problem with Big Sur. I solved it by running:
export JAVA_HOME="$(/usr/libexec/java_home -v 1.8)"
to set up a path maybe? I am not sure what is export means but that works for me.
(by the way, this is the first time I solve a problem for people on any types of forum)

@tdwong

This comment has been minimized.

Copy link

@tdwong tdwong commented Sep 10, 2021

On Big Sur, I am getting following error after everything was built. Does anyone know how to turn off code signing check?

$ java -Djava.library.path=. JNIExample
Exception in thread "main" java.lang.UnsatisfiedLinkError: /Users/twong/Workspace/java/JNI/jni-example-mac/libjniexample.jnilib: dlopen(/Users/twong/Workspace/java/JNI/jni-example-mac/libjniexample.jnilib, 1): no suitable image found.  Did find:
	/Users/twong/Workspace/java/JNI/jni-example-mac/libjniexample.jnilib: code signing blocked mmap() of '/Users/twong/Workspace/java/JNI/jni-example-mac/libjniexample.jnilib'
	at java.base/jdk.internal.loader.NativeLibraries.load(Native Method)
	at java.base/jdk.internal.loader.NativeLibraries$NativeLibraryImpl.open(NativeLibraries.java:383)
	at java.base/jdk.internal.loader.NativeLibraries.loadLibrary(NativeLibraries.java:227)
	at java.base/jdk.internal.loader.NativeLibraries.loadLibrary(NativeLibraries.java:169)
	at java.base/jdk.internal.loader.NativeLibraries.findFromPaths(NativeLibraries.java:316)
	at java.base/jdk.internal.loader.NativeLibraries.loadLibrary(NativeLibraries.java:282)
	at java.base/java.lang.ClassLoader.loadLibrary(ClassLoader.java:2416)
	at java.base/java.lang.Runtime.loadLibrary0(Runtime.java:808)
	at java.base/java.lang.System.loadLibrary(System.java:1893)
	at JNIExample.<clinit>(JNIExample.java:16)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment