All Projects → thefangbear → Jni By Examples

thefangbear / Jni By Examples

Licence: mit
🎇Fun Java JNI By Examples - with CMake and C++ (or C, of course!) ‼️ Accepting PRs

Programming Languages

java
68154 projects - #9 most used programming language
c
50402 projects - #5 most used programming language
cpp
1120 projects

Projects that are alternatives of or similar to Jni By Examples

Wordpress Plugin Boilerplate Tutorial
Tutorials and Examples for WordPress Plugin Boilerplate, a foundation for WordPress Plugin Development.
Stars: ✭ 232 (+134.34%)
Mutual labels:  tutorial, example, examples, example-project
Godot tutorials
Code and examples for KidsCanCode Godot Tutorials.
Stars: ✭ 119 (+20.2%)
Mutual labels:  tutorial, example, examples, example-project
play-java-ebean-example
Example Play application showing Java with Ebean
Stars: ✭ 54 (-45.45%)
Mutual labels:  jvm, example, example-project
play-scala-anorm-example
Example Play Database Application using Anorm
Stars: ✭ 41 (-58.59%)
Mutual labels:  jvm, example, example-project
lagom-samples
developer.lightbend.com/start/?group=lagom
Stars: ✭ 85 (-14.14%)
Mutual labels:  jvm, example, example-project
play-java-rest-api-example
REST API using Play in Java
Stars: ✭ 44 (-55.56%)
Mutual labels:  jvm, example, example-project
play-scala-streaming-example
Example Play application showing Comet and Server Sent Events in Scala
Stars: ✭ 42 (-57.58%)
Mutual labels:  jvm, example, example-project
Play Scala Slick Example
Example Play Scala project with Slick
Stars: ✭ 59 (-40.4%)
Mutual labels:  example, example-project, jvm
Avenging
MVP pattern example on Android: no Dagger or RxJava example
Stars: ✭ 279 (+181.82%)
Mutual labels:  api, tutorial, example
Play Samples
Stars: ✭ 335 (+238.38%)
Mutual labels:  example, example-project, jvm
Learning Rust
Rust 学习之路 > Rust Programming Tutorial, include articles, interview, example, problems.
Stars: ✭ 376 (+279.8%)
Mutual labels:  tutorial, example, examples
play-scala-seed.g8
Play Scala Seed Template: run "sbt new playframework/play-scala-seed.g8"
Stars: ✭ 66 (-33.33%)
Mutual labels:  jvm, example, example-project
Examples
Examples of Mock Service Worker usage with various frameworks and libraries.
Stars: ✭ 163 (+64.65%)
Mutual labels:  api, example, examples
play-scala-chatroom-example
Play chatroom with Scala API
Stars: ✭ 43 (-56.57%)
Mutual labels:  jvm, example, example-project
Learning Cmake
learning cmake
Stars: ✭ 2,524 (+2449.49%)
Mutual labels:  cmake, tutorial, example
play-scala-secure-session-example
An example Play application showing encrypted session management
Stars: ✭ 54 (-45.45%)
Mutual labels:  jvm, example, example-project
Haxejs
Documentation about using JavaScript with Haxe
Stars: ✭ 25 (-74.75%)
Mutual labels:  tutorial, example, examples
Wasm By Example
Wasm By Example is a website with a set of hands-on introduction examples and tutorials for WebAssembly (Wasm)
Stars: ✭ 226 (+128.28%)
Mutual labels:  tutorial, example, examples
Vaporschool
Learn how to build vapor applications from rookie to champion in a constructive way!
Stars: ✭ 259 (+161.62%)
Mutual labels:  tutorial, example, examples
Rxjava2 Android Samples
RxJava 2 Android Examples - Migration From RxJava 1 to RxJava 2 - How to use RxJava 2 in Android
Stars: ✭ 4,950 (+4900%)
Mutual labels:  tutorial, example, examples

(Introductory) Java Native Interface Programming, By Examples

Notice: I'm now considering adding content to this tutorial. If you have proposals or new additions, please don't hesitate to contribute.

Table of contents

Foreword

Note: I wrote this in early 2017 because of a need to offload image serialization tasks to C++ from Java (Java's GC,bad bad!) But now things may have changed with newer versions of Java 8 and 9. This repository is now seldomly updated, but you may still take it as a simple reference guide to get started. JNI is quite simple to program, and the most difficult bit of it is to actually load your dynamic library from your jar file. If you're good with C/C++, you shall be quite easily bootstrapped after reading some material.

Note 2: This example also shows you how to use CMake to compile your source files for JNI!

This is an examples repository for Java's JNI. The codes are written in C++ and Java, properly demonstrating the correct way to interact with JNI through tools like javah and javac. Alternatively, the CMakeLists.txt utilizes CMake to compile the C++ library along with JNI implementations, and the jnihelper.sh shell script provides decent helper utilities to rapidly prototype a JNI library.

A Written Introduction to Java Native Interface Programming

Part I: Writing a Java file that interfaces C/C++ Programs

Write something like java/in/derros/jni/Utilities.java. You can see the native keyword describes the functions and/or methods in C and C++ you want to interface Java with. Great. Now we have a java file. For a file located in a package, we use

javac path/to/package/name/Class.java

to compile. For regular class files, we use

javac ClassName.java

to compile. After executing the command, you should see a .class file located under the same directory the .java source file is in. Great. Now we have a Java classfile.

Part I.2: Generating C/C++ JNI Headers

Now we have to find a way to plug ourselves into JVM via JNI. This is incredibly easy, we do:

javah ClassName

or for classes inside packages:

javah package.name.ClassName

And now you'll find a strangely named (but not utterly random) .h header file in the directory you called javah. Now here's the crucial step: writing the actual implementation according to the header.

Part II: A glimpse into the JNI environment

A typical header file such as java/*.h exists a bunch of oddly shaped C++/C function declarations. However, you'll have to write the actual implementations yourself in a separate cpp or c file that references the header. Implementation is complete as long as you write specific implementations for each and every method. After that it's as easy as building everything into a shared library using cmake (which is really a piece of cake, if you have JVM properly installed and configured).

A typical JNI function with a void return has a signature like this (for example):

JNIEXPORT void JNICALL Java_in_derros_jni_Utilities_printMethod
        (JNIEnv *env, jobject obj)

Note that env is especially helpful. For C++ guys env is a pointer to an instance of a class allocated on the heap (not exactly true but you can reason like that to help you navigate through) and for C guys the env variable is simply a pointer to a structure passed in, where the structure stores a bunch of function pointers you can use to access a bunch of JVM internal functions. A decent IDE is recommended here, as it saves you countless amounts of time to make you peek into these variables yourself, but you also can find sample implementations of functions of different return types (sometimes even iterator examples) in the sourcecode folder of this project. For the C++ implementation of JNI functions, you can find in Utils.cpp - and for all the java-related header files and class files you can find in the java/ folder.

Now, time for some examples...

Example 1: Converting a C++ vector to a Java ByteArray and return

    jbyteArray __ba = env->NewByteArray(3);
    std::vector<unsigned char> __c_vec(3);
    __c_vec[0] = 0;
    __c_vec[1] = 1;
    __c_vec[2] = 1;
    unsigned char * __c_ptr = __c_vec.data();
    env->SetByteArrayRegion (__ba, 0, 3, reinterpret_cast<jbyte*>(__c_ptr));
    std::cout << "Printing Byte Array members..." << std::endl;
    std::for_each(__c_vec.begin(), __c_vec.end(), [](const char &c) { std::cout << c ; });
    std::cout << std::endl << std::endl;
    return __ba;

Note: env is provided in every JNI call to C++.

Example 2: Manipulating Java Strings in C++

(Well, actually not too accurate. We're copying over the string as a C char*, doing the manipulation, and returning one back)

   std::string s = env->GetStringUTFChars(str, (jboolean)false);
    std::cout << "NOW IN NATIVE STRING ENVIRONMENT!!" << std::endl;
    std::cout << "Your caller says: " << s << std::endl;
    std::cout << "Now iterating over the given string array." << std::endl;
    // iterate over
    for(int i = 0; i < env->GetArrayLength(strObj1); i++) {
        std::cout
                << env->GetStringUTFChars((jstring)env->GetObjectArrayElement(strObj1, (jsize)i), (jboolean)false)
                << std::endl;
    }
    s.append("::::::THIS IS APPENDED TEXT!!!! WARNING!!! WARNING!!!! :)");
    return env->NewStringUTF(s.data());

Example 3: Returning a boolean

This is to show that most of the primitive types are provided by the JNI header files. For example, a boolean is denoted by jboolean. The best way to code is to employ an IDE or use CTags to scan for types in the JNI header file.

    std::cout << "BOOL VALUE: 1 (True)" << std::endl;
    jboolean b = 1;
    return b;

A Practical Tip: Don't be afraid of casting! JNI is amazingly tolerant for casting between C primitive types and j-prefixed types. However, for most C++-specific objects, some manual labour is needed. A Java byte is roughly equal to a C++ char/unsigned char.

For more examples and getting a general "gist" of JNI to start, view the source code of this repository.

This is about the end of your journey/actually coding/ a JNI application. Good luck!

Finale: Build

Build is dramatically easy on systems with CMake as CMake provides a default functionality of finding the appropriate JNI files. To build, type in:

mkdir build/
cd build/
cmake ../
make

And then you'll see the libjnitests.so file shiningly appearing under the build directory! For windows guys it's libjnitests.dll and for MacOS guys it's libjnitests.dylib, but they're really all the same.

The final steps is really modifying the Java source file for it to load from the appropriate library using System.load or System.loadLibrary (with is extra tricky-dicky), and cross your fingers for good luck! If you have any extra questions (which I'm pretty sure you have) due to the time limits I cannot describe more of the housekeeping work here. Proceed to jnihelper.sh and have a look at the prototypical shell script's implementations. I'm sure you'll find some inspirations there.

Remarks

Till now, you should be programming yourself away in JNI. JNI is a content-rich and powerful interface worth exploring. Happy hacking!

Author

Copyright © Rui-Jie Fang 2018.

License

Licensed under the MIT License.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].