Skip to content

Instantly share code, notes, and snippets.

@DmitrySoshnikov
Last active May 1, 2024 05:02
Show Gist options
  • Star 25 You must be signed in to star a gist
  • Fork 11 You must be signed in to fork a gist
  • Save DmitrySoshnikov/8b1599a5197b5469c8cc07025f600fdb to your computer and use it in GitHub Desktop.
Save DmitrySoshnikov/8b1599a5197b5469c8cc07025f600fdb to your computer and use it in GitHub Desktop.

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
Copy link

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
Copy link

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
Copy link

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
Copy link

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)

@tyagi2141
Copy link

tyagi2141 commented Feb 8, 2023

Hi @zzhou37 ,in your case you need to Download the file from from github https://github.com/openjdk/jdk/blob/master/src/java.base/share/native/include/jni.h and save both jni.h and your code in same folder and then try to run it

@MrWangFeiHu
Copy link

Hello, When I run the command:
java -Djava.library.path=. JNIExample

I got the error:

Exception in thread "main" java.lang.UnsatisfiedLinkError: no jniexample in java.library.path
	at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1863)
	at java.lang.Runtime.loadLibrary0(Runtime.java:843)
	at java.lang.System.loadLibrary(System.java:1134)
	at JNIExample.<clinit>(JNIExample.java:16)

env: MacOS Monterey 12.3

$gcc -v
Apple clang version 13.1.6 (clang-1316.0.21.2.5)
Target: arm64-apple-darwin21.4.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
$java -version
java version "1.8.0_351"
Java(TM) SE Runtime Environment (build 1.8.0_351-b10)
Java HotSpot(TM) 64-Bit Server VM (build 25.351-b10, mixed mode)

Do yo know how to solve this error? thank you very much.

@midhunadarvin
Copy link

midhunadarvin commented May 1, 2024

Hello, When I run the command: java -Djava.library.path=. JNIExample

I got the error:

Exception in thread "main" java.lang.UnsatisfiedLinkError: no jniexample in java.library.path
	at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1863)
	at java.lang.Runtime.loadLibrary0(Runtime.java:843)
	at java.lang.System.loadLibrary(System.java:1134)
	at JNIExample.<clinit>(JNIExample.java:16)

env: MacOS Monterey 12.3

$gcc -v
Apple clang version 13.1.6 (clang-1316.0.21.2.5)
Target: arm64-apple-darwin21.4.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
$java -version
java version "1.8.0_351"
Java(TM) SE Runtime Environment (build 1.8.0_351-b10)
Java HotSpot(TM) 64-Bit Server VM (build 25.351-b10, mixed mode)

Do yo know how to solve this error? thank you very much.

Getting the same error in MacOS M1 . .so and .jnilib doesn't work for me.

EDIT :

Figured it out by referring this : https://www.baeldung.com/jni

Compile ( MacOS ) :

g++ -c -fPIC -I"${JAVA_HOME}/include" -I"${JAVA_HOME}/include/darwin" JNIExample.c -o JNIExample.o

Link ( MacOS ) :

g++ -dynamiclib -o libjniexample.dylib JNIExample.o -lc

Run :

java -cp . -Djava.library.path=. JNIExample

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment