JNI example

There is a useful tutorial on JNI: See Java Programming Tutorial Java Native Interface (JNI).

Save the following file as HelloJNI.java:


// Save as HelloJNI.java
public class HelloJNI 
{  
   static 
   {
      System.loadLibrary("hello"); // Load native library hello.dll (Windows) or libhello.so (Unixes)
                                   //  at runtime
                                   // This library contains a native method called sayHello()
   }
 
   // Declare an instance native method sayHello() which receives no parameter and returns void
   private native void sayHello();
 
   // Test Driver
   public static void main(String[] args) 
   {
      new HelloJNI().sayHello();  // Create an instance and invoke the native method
   }
}

Generate the header with the following command

    "C:\Program Files\Java\jdk-12.0.1\bin\javac" -h . HelloJNI.java

This generates:


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

#ifndef _Included_HelloJNI
#define _Included_HelloJNI
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     HelloJNI
 * Method:    sayHello
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_HelloJNI_sayHello
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

Provide the implementation in HelloJNI.cpp:


// Save as "HelloJNI.cpp"
#include <jni.h>        // JNI header provided by JDK
#include <stdio.h>      // C Standard IO Header
#include "HelloJNI.h"   // Generated
 
// Implementation of the native method sayHello()
JNIEXPORT void JNICALL Java_HelloJNI_sayHello(JNIEnv *env, jobject thisObj) 
{
   printf("Hello World!\n");
   return;
}

Use the following CMakeLists.txt file to build the JNI library


# CMakeLists.txt
cmake_minimum_required(VERSION 3.5)
 
project(HelloJNI VERSION 0.1 LANGUAGES CXX)

find_package(Java REQUIRED)

message("JAVA_HOME = ${JAVA_HOME}")
message("Java_JAVA_EXECUTABLE = ${Java_JAVA_EXECUTABLE}")
message("Java_JAVAC_EXECUTABLE = ${Java_JAVAC_EXECUTABLE}")
message("Java_JAVAH_EXECUTABLE = ${Java_JAVAH_EXECUTABLE}")
message("Java_JAVADOC_EXECUTABLE = ${Java_JAVADOC_EXECUTABLE}")
message("Java_VERSION_STRING = ${Java_VERSION_STRING}")
message("Java_VERSION = ${Java_VERSION}")

find_package(JNI)

if (JNI_FOUND)
    # -- JNI_INCLUDE_DIRS=C:/Program Files/Java/jdk1.8.0_191/include;C:/Program Files/Java/jdk1.8.0_191/include/win32;C:/Program Files/Java/jdk1.8.0_191/include
    # -- JNI_LIBRARIES=C:/Program Files/Java/jdk1.8.0_191/lib/jawt.lib;C:/Program Files/Java/jdk1.8.0_191/lib/jvm.lib
    message (STATUS "JNI_INCLUDE_DIRS=${JNI_INCLUDE_DIRS}")
    message (STATUS "JNI_LIBRARIES=${JNI_LIBRARIES}")
endif()

add_compile_options(/std:c++latest)

#include_directories(${JAVA_HOME}/include)
#include_directories(${JAVA_HOME}/include/win32)

add_library(HelloJNI SHARED HelloJNI.cpp)
target_include_directories(HelloJNI PRIVATE 
    ${JAVA_HOME}/include                            # Has jni.h
    ${JAVA_HOME}/include/win32)

Use the following batch file to run cmake


@ECHO OFF

SET MGF=%CD%
SET BUILD=%MGF%\build

SET VCVARS64=%ProgramFiles(x86)%\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat
SET VCVARS32=%ProgramFiles(x86)%\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars32.bat

SET WINDOWS_COMPILER="cl.exe"
::SET WINDOWS_COMPILER="C:/Program Files/LLVM/bin/clang-cl.exe"

SET CONFIG=RelWithDebInfo

CALL "%VCVARS64%"

MKDIR "%BUILD%\x64-Release"
CD "%BUILD%\x64-Release"
	
cmake -G "Ninja" ^
-DJAVA_HOME="C:/Program Files/Java/jdk-12.0.1" ^
-DCMAKE_INSTALL_PREFIX:PATH="%BUILD%\install\x64-Release" ^
-DCMAKE_TOOLCHAIN_FILE="%VCPKG_ROOT_DIR%/scripts/buildsystems/vcpkg.cmake" ^
-DCMAKE_WINDOWS_EXPORT_ALL_SYMBOLS="TRUE" ^
-DCMAKE_CXX_COMPILER=%WINDOWS_COMPILER% ^
-DCMAKE_C_COMPILER=%WINDOWS_COMPILER% ^
-DCMAKE_BUILD_TYPE=%CONFIG% ^
-DCMAKE_MAKE_PROGRAM=ninja ^
--config RelWithDebInfo ^
"%MGF%"

cmake --build . --target install --config %CONFIG%

CD %MGF%
COPY "%BUILD%\x64-Release\hello.dll" .

PAUSE

Now run the Java program:

    "C:\Program Files\Java\jdk-12.0.1\bin\java" -cp . HelloJNI