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