• Stars
    star
    156
  • Rank 239,589 (Top 5 %)
  • Language
    C
  • License
    Other
  • Created over 3 years ago
  • Updated almost 2 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

JNI Cookbook Redux - learn JNI by example.

Download

If you are interested in stories with happy endings, you would better of reading some other book. In this book, not only there is no happy ending, there is no happy beginning, and very few happy things in the middle.

-- Lemony Snicket, The Bad Beginning

Inside this book you can find JNI related codes that I have written over years of working with JNI. I was typically preparing small samples to test some particular concepts. Sometimes, I was preparing solutions for people who were desparatelly looking for help on stackoverflow. There is a companion material in form of text, figures, where I describe some topics in details. JNI Cookbook page can be found here: JNI Cookbook. Please note that I had no time, yet, to prepare nice and detailed explanation for each end every contept that is tackled in this book.

Building and running

Seeing is believing. This is why I have decided to provide people with not only the description of some concepts, but with working sample code as well. The code you can find in this repository is an integral part of the book.

The easiest way to build and run codes is to clone the repository 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-17.0.1.jdk/...
...
> make test
/Library/Java/JavaVirtualMachines/jdk-17.0.1.jdk/...
library: :./lib
Hello world!

Ready for Java 8 and onwards

JNI Cookbook samples were adapted to Java 17 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
  • JDK 15
  • JDK 16
  • JDK 17

Debugging

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, TotalView, lldb). When it comes to debugging JNI code, you can find some hints inside JNI Cookbook as well. Even more, you can find a screencast that demonstates how to debug JNI code using IntelliJ IDEA and CLion. In fact, there are more to come. I plan to prepare one that will discuss lldb, one for gdb, and last but not least one for TotalView (this is, however, song of the future).

Requirements

At the moment, JNI Cookbook targets Linux and macOS. It should work on both platforms without any issues.

Setting up macOS system for JNI Cookbook

Make sure to install XCode. Once installed, perform installation of Command Line Tools.

Make sure to install OpenJDK 17 or Java SE Development Kit 17).

Once installed, make sure to set JAVA_HOME following way

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

If you are one of those brave people who like to live at the edge, you can use the most recent version of OpenJDK - JDK 19.

Once installed, make sure to set JAVA_HOME following way

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

Setting up Ubuntu system for JNI Cookbook

sudo apt install openjdk-17-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}

Setting up Scala

JNI Cookbook contains Scala based samples. 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 3.0.1 and sbt 1.6.0.

Nobody has time for that!

Are you crazy? Do you think I have time for all that setup?

You are right, nobody has time for that. This is why this product comes with self sufficient, ready for immediate use, Docker file. Once you start the container, everything is there. All you have to do is to build the image and run the container.

> cd docker
> docker build -t jnicookbook .
> docker run -it jnicookbook

that's it. That's all you have to do, to get all the JNI Cookbook samples ready for testing.

It's no good reading about JNI in 2021

I won't force you to do so, but you are always welcome to read this book.

I think this book is bad

I think your book is not really that good (as some people say) and it's not interesting at all.

I totally agree. After all, this is a book related to low level coding. Have you ever read really interesting book that was describing low level coding? I really doubt it. These kind of books can be informative, they might be useful, but calling them entartaining, and really good books - that's euphemism.

Live is way too short to read dull books - like this one. This is why I have prepared a list of books you should have read instead. Each week, I will post a new book that is definitely more exciting and definitely worth way more of your time rather than this one. Stay tuned. List of books that are way more interesting.

I don't like your book

I can't make everybody happy. Make sure to double check previous points.

I think you should ...

No, thank you.

I think it would be better if ...

No, thank you.

Bibliography

This book wouldn't have existed if there were no great books on various topics it tackles.

  • Java Native Interface Specification, by Oracle
  • The Native Intefrace, by S. Liang
  • Programming in Scala, by M. Odersky
  • JNA documentation, by JNA project
  • Komunikacja miedzy procesami w Unixie, by J. S. Gray (tlumaczenie: P. Kresak)
  • The C Programming Language, by B.W. Kernighan, D. M. Ritchie
  • C++, by B. Stroustrup

I always try to quote places I got inspiration from. Sometimes it's really hard to address each and every line of the code. If some quotations are still missing, it is unintentional. If you think I have missed some well known sources, please let me know, and I am happy to double check the source and update the Bibliography section if necesary.

Table of contents - JNI based code

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Ā ā„–Ā 078 Surprize, surprize ! My stack is so small. [source]
recipeĀ ā„–Ā 079 Passing String value from C via object passed as an argument[source]
recipeĀ ā„–Ā 080 Parsing string with date inside JNI [source]
recipeĀ ā„–Ā D001 debugging JNI code with CLion [source]
recipeĀ ā„–Ā D003 Profiling JNI based code using Instruments.app (macOS only) [source]

Download


Copyright Ā© 2015-2022 Michal K. Owsiak. All rights reserved.