📓 Archive

JNI

FGJ: Create:2023/11/17 Update: [2024-11-21]

example #

1. 写一段包含C方法实现的java代码 #
// Save as HelloJNI.java
public class HelloJNI{
    static {
        // Load native library hello.dll (Windows) or libhello.so (Unixes) at runtime
        // This library contains a native method called sayHello()
        System.loadLibrary("hello");
    }
    // Declare an instance native method sayHello() which receives no parameter and returns void
    private native void sayHello();
    public static void main(String[] args){
        // Create an instance and invoke the native method
        new HelloJNI().sayHello();
    }
}

The static initializer invokes System.loadLibrary() to load the native library “hello” (which contains a native method called sayHello()) during the class loading. It will be mapped to “hello.dll” in Windows; or “libhello.so” in Unixes/Mac OS X. This library shall be included in Java’s library path (kept in Java system variable java.library.path). You could include the library into Java’s library path via VM argument -Djava.library.path=/path/to/lib. The program will throw a UnsatisfiedLinkError if the library cannot be found in runtime.

2. 编译HelloJNI.java 并且生成C/C++头文件 HelloJNI.h #

Starting from JDK 8, you should use “javac -h” to compile the Java program AND generate C/C++ header file called HelloJNI.h as follows:
javac -h . HelloJNI.java
The “-h dir” option generates C/C++ header and places it in the directory specified (in the above example, ‘.’ for the current directory).

Before JDK 8, you need to compile the Java program using javac and generate C/C++ header using a dedicated javah utility, as follows. The javah utility is no longer available in JDK 10.
javac HelloJNI.java
javah HelloJNI

/* 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
3. 实现C语言代码 #
// Save as "HelloJNI.c"
#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;
}
4. 编译HelloJNI.c #
  1. Set environment variable JAVA_HOME to point to the JDK installed directory (which shall contains the include subdirectory to be used in the next step):
$ export JAVA_HOME=/your/java/installed/dir
   // for my machine @ /Library/Java/JavaVirtualMachines/jdk1.8.0_xx.jdk/Contents/Home
$ echo $JAVA_HOME
  1. Compile the C program HelloJNI.c into dynamic share module libhello.dylib using gcc, which is included in all Unixes/Mac OS:
$ gcc -I"$JAVA_HOME/include" -I"$JAVA_HOME/include/darwin" -dynamiclib -o libhello.dylib HelloJNI.c
  1. Run the Java Program:
$ java -Djava.library.path=. HelloJNI
  1. Set environment variable JAVA_HOME to point to the JDK installed directory (which shall contains the include subdirectory to be used in the next step):
$ export JAVA_HOME=/your/java/installed/dir
$ echo $JAVA_HOME
  1. Compile the C program HelloJNI.c into share module libhello.so using gcc, which is included in all Unixes:
$ gcc -fPIC -I"$JAVA_HOME/include" -I"$JAVA_HOME/include/linux" -shared -o libhello.so HelloJNI.c
  1. Run the Java Program:
$ java -Djava.library.path=. HelloJNI
5. 记录 #

1. 使用C++代替C语言中的第三步 #
// Save as "HelloJNI.cpp"
#include <jni.h>       // JNI header provided by JDK
#include <iostream>    // C++ standard IO header
#include "HelloJNI.h"  // Generated
using namespace std;

// Implementation of the native method sayHello()
JNIEXPORT void JNICALL Java_HelloJNI_sayHello(JNIEnv *env, jobject thisObj) {
	cout << "Hello World from C++!" << endl;
   return;
}
2. 编译动态链接库 #
$ g++ -I"$JAVA_HOME/include" -I"$JAVA_HOME/include/darwin" -dynamiclib -o libhello.dylib HelloJNI.cpp
3. 记录 #

1. 写一段 HelloJNICpp.java 代码 #
public class HelloJNICpp {
    static {
        // hello.dll (Windows) or libhello.so (Unixes)
        System.loadLibrary("hello"); 
    }

    // Native method declaration
    private native void sayHello();
 
    // Test Driver
    public static void main(String[] args) {
        // Invoke native method
        new HelloJNICpp().sayHello();  
    }
}
2. 编译出头文件HelloJNICpp.h #
$ javac -h . HelloJNICpp
3. 实现C/C++ - HelloJNICppImpl.h, HelloJNICppImpl.cpp, and HelloJNICpp.c #
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class HelloJNICpp */

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

#ifdef __cplusplus
}
#endif
#endif
#include <jni.h>
#include "HelloJNICpp.h"
#include "HelloJNICppImpl.h"
 
JNIEXPORT void JNICALL Java_HelloJNICpp_sayHello (JNIEnv *env, jobject thisObj) {
    sayHello();  // invoke C++ function
    return;
}
#ifndef _HELLO_JNI_CPP_IMPL_H
#define _HELLO_JNI_CPP_IMPL_H
 
#ifdef __cplusplus
        extern "C" {
#endif
        void sayHello ();
#ifdef __cplusplus
        }
#endif
 
#endif
#include "HelloJNICppImpl.h"
#include  <iostream>
 
using namespace std;
 
void sayHello () {
    cout << "Hello World from C++, this is mixture!" << endl;
    return;
}
4. 编译动态链接库 #
# 添加 -lc++ ,用来链接 C++ 标准库
$ gcc -I"$JAVA_HOME/include" -I"$JAVA_HOME/include/darwin" -lc++  -dynamiclib -o libhello.dylib HelloJNICpp.c HelloJNICppImpl.cpp
5. 记录 #

Reference #


comments powered by Disqus