Inside this repository you can find JNI related codes that I have collected over years of working with JNI. You can also find a companion book, where I describe some topics in details. JNI Cookbook page can be found here: JNI Cookbook
The easiest way to build and run codes is to clone the repo and run all tests.
> git clone https://github.com/mkowsiak/jnicookbook.git
> cd jnicookbook/recipes
> make all
> make test
> make clean
Remember that you can always run each and every sample separatelly. Simply call make
inside given recipe. Let's say you want to run recipeNo001
. All you have to do is to run
> cd jnicookbook/recipes/recipeNo001
> make
/Library/Java/JavaVirtualMachines/jdk-14.jdk/...
...
> make test
/Library/Java/JavaVirtualMachines/jdk-14.jdk/...
library: :./lib
Hello world!
JNI Cookbook samples were adapted to Java 14
release. You shouldn't experience any issues while working with most recent release of Java. If you have stuck with Java 8
- for any reasons - you should be able to use samples as well.
JNI Cookbook samples were tested with:
- JDK 1.8
- JDK 9
- JDK 10
- JDK 11
- JDK 12
- JDK 13
- JDK 14
Debugging JNI code is not quite like sitting on cloud nine. You have to attach to JVM where JNI code is running and debug native code using external tools (e.g.: gdb
, CLion
). When it comes to debugging JNI code, you can find some hints inside JNICookbook as well. Even more, you can find a screencast that demonstates how to debug JNI code using IntelliJ IDEA
and CLion
At the moment, JNI Cookbook targets Linux and macOS. It should work on both platforms without any issues.
Make sure to install XCode. Once installed, perform installation of Command Line Tools
.
Make sure to install OpenJDK or Java SE Development Kit 13).
Once installed, make sure to set JAVA_HOME
following way
export JAVA_HOME=$(/usr/libexec/java_home -v 13)
If you are one of those brave people, you can use the most recent version of OpenJDK - JDK 14.
Once installed, make sure to set JAVA_HOME
following way
export JAVA_HOME=$(/usr/libexec/java_home -v 14)
sudo apt install openjdk-13-jdk
sudo apt install git
sudo apt install make
sudo apt install gcc
sudo apt install g++
# Inside JNI Cookbook, all the Java stuff is based on JAVA_HOME
# variable - you need it inside the env.
export JAVA_HOME=`readlink -f $(which java) | sed 's|/bin/java||'`
# We need ./lib on LD_LIBRARY_PATH
# Rememer that inside JNI code we no longer use java.library.path
# when it comes to resolving location of the shared library.
# Inside JNI we base on system's way of locating the lib.
export LD_LIBRARY_PATH=./lib:${LD_LIBRARY_PATH}
JNI Cookbook contains Scala
based samplesi. These samples are using JNA
to call native code. Please make sure to install most recent version of Scala
and sbt
. This will allow you to avoid following error:
Exception in thread "main" java.io.IOError:
java.lang.RuntimeException: /packages cannot be represented as URI
At the time of writing these versions were, respectivelly: Scala 2.13.1 and sbt 1.3.7.
Recipe № | Short description |
---|---|
recipe № 001 | running simple JNI code [source] |
recipe № 002 | passing int value from Java to C [source] |
recipe № 003 | passing double value from Java to C [source] |
recipe № 004 | passing long value from Java to C [source] |
recipe № 005 | passing short value from Java to C [source] |
recipe № 006 | passing char value from Java to C [source] |
recipe № 007 | passing byte value from Java to C [source] |
recipe № 008 | passing boolean value from Java to C [source] |
recipe № 009 | passing java.lang.String value from Java to C [source] |
recipe № 010 | passing java.lang.String value from C to Java [source] |
recipe № 011 | passing primitive types from C to Java [source] |
recipe № 012 | passing primitives array from Java to C [source] |
recipe № 013 | passing primitives array from Java to C and back (commit changes) [source] |
recipe № 014 | passing memory allocated in C back to Java [source] |
recipe № 015 | handling SIGSEGV/SIGBUS in JNI code (stop JVM from crashing) [source] |
recipe № 016 | handling exit calls from external library called via JNI (atexit) [source] |
recipe № 017 | handling exit calls from external library called via JNI (-Dexit) [source] |
recipe № 018 | dynamic loading of library in JNI [source] |
recipe № 019 | throwing exception from C code [source] |
recipe № 020 | accessing fields of object passed as argument [source] |
recipe № 021 | calling function from different source file [source] |
recipe № 022 | Java based daemon [source] |
recipe № 023 | calling code from another shared library [source] |
recipe № 024 | calling JNI methods from Threads and how to debug them using gdb [source] |
recipe № 025 | calling C++ code from C wrapper [source] |
recipe № 026 | passing 2D arrays from Java to C [source] |
recipe № 027 | Calling class methods from multiple threads [source] |
recipe № 028 | Calling JVM class from C (first draft for thread based computations) [source] |
recipe № 029 | Running Java as daemon – main daemon’s loop in Java [source] |
recipe № 030 | Abstract method and native implementation [source] |
recipe № 031 | Running simple JNI code from inside JAR file [source] |
recipe № 032 | Calling JVM from multiple C threads [source] |
recipe № 033 | Comparing execution time of "Hello world!" executed from JNI/JNA/ProcessBuilder [source] |
recipe № 034 | Running simple JNI code from Outer class and Inner class [source] |
recipe № 035 | Running simple JNI code from inside JAR file with libraries it depends on [source] |
recipe № 037 | Passing HashMap to C code via JNI [source] |
recipe № 038 | Passing HashMap to C code via JNI (using two arrays) [source] |
recipe № 039 | Calling (from C) Java method that returns 2D array [source] |
recipe № 040 | Passing ByteBuffer to C code via JNI [source] |
recipe № 042 | Passing Set of Strings to C code via JNI [source] |
recipe № 043 | Settings environment variable inside JVM via JNI [source] |
recipe № 044 | Getting info (inside JNI code) regarding current thread using java.lang.Thread [source] |
recipe № 045 | Returning vector<vector > from C++ to Java [source] |
recipe № 046 | Filling java.util.List (passed to JNI) with data - inside C++ [source] |
recipe № 047 | Filling java.util.HashMap (passed to JNI) with data - inside C++ [source] |
recipe № 048 | Returning map<int, int> from C++ to Java [source] |
recipe № 049 | Redirecting JVM's System.out to file inside C code [source] |
recipe № 050 | How to find location of JAR from JNI [source] |
recipe № 051 | Very simple, Java based, 'Hello world' code - calling it from C [source] |
recipe № 052 | Registering native symbols without System.load [source] |
recipe № 053 | Accessing elements of array - GetByteArrayElements vs. GetPrimitiveArrayCritical [source] |
recipe № 054 | Hello Scala! [source] |
recipe № 055 | Unboxing primitive types from wrapper objects - method per type [source] |
recipe № 056 | Unboxing primitive types from wrapper objects - one method and IsInstanceOf [source] |
recipe № 057 | Hello Scala! I am passing structures! [source] |
recipe № 058 | Passing "unsigned long" to JNI [source] |
recipe № 059 | Using code from static library inside JNI based code [source] |
recipe № 060 | How to run Java code (with Log4j) from C [source] |
recipe № 061 | Passing std::map<std::string, std::string> from C++ to Java [source] |
recipe № 063 | Accessing fields of inner class [source] |
recipe № 064 | Running simple JNI code - using JDK9 modules [source] |
recipe № 065 | Very simple, Java based, 'Hello world' code - calling it from Objective-C (macOS only) [source] |
recipe № 066 | Embedding JVM inside macOS application bundle and calling JVM from Objective-C (macOS only) [source] |
recipe № 067 | Iterating over objects inside java.util.List - using get method [source] |
recipe № 068 | Iterating over objects inside java.util.List - using java.util.Iterator [source] |
recipe № 069 | Iterating over objects inside array of Objects (SimpleBean[]) [source] |
recipe № 070 | Passing structure by reference using JNA [source] |
recipe № 071 | Be carefull with errno. It can bite. [source] |
recipe № 072 | Handling errno using custom exception type [source] |
recipe № 073 | Passing errno and errno string inside wrapper class [source] |
recipe № 074 | Passing errno via JNI routine's arguments [source] |
recipe № 075 | Returning object with number of fields from JNI (constructor) [source] |
recipe № 076 | Returning object with number of fields from JNI (setters) [source] |
recipe № 077 | Passing null as method argument inside JNI [source] |
recipe № D001 | debugging JNI code with CLion [source] |
recipe № D003 | Profiling JNI based code using Instruments.app (macOS only) [source] |