Java的JNI机制
Java还有一个JNI机制,它的全称:Java Native Interface,即Java本地接口。它允许在Java虚拟机内运行的Java代码与其他编程语言(如C/C++和汇编语言)编写的程序和库进行交互(在Android开发中用得比较多)
简单举例:我们现在想要让C++语言程序帮助我们的Java程序实现a+b的运算,首先我们需要创建一个本地方法:
1 2 3 4 5 6 7 8 9 10
| package com.test;
public class Main { public static void main(String[] args) { System.out.println(sum(1,2)); } public static native int sum(int a,int b); }
|
创建好后,接着点击构建按钮,会出现一个out文件夹,也就是生成的class文件在其中

接着我们直接生成对应的C头文件:
(注意,这条指令基于jdk1.8实现,jdk版本过高 请使用javac -h指令)
1
| javah -classpath out/production/pro02 -d ./jni com.test.Main
|
生成的头文件位于jni文件夹下:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| #include <jni.h>
#ifndef _Included_com_test_Main #define _Included_com_test_Main #ifdef __cplusplus extern "C" { #endif
JNIEXPORT void JNICALL Java_com_test_Main_sum (JNIEnv *, jclass, jint, jint);
#ifdef __cplusplus } #endif #endif
|
接着我们在CLion中新建一个C++项目,引入刚刚生成的头文件并导入jni相关头文件(在JDK文件夹中)
首先修改CMake文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| cmake_minimum_required(VERSION 3.20) project(pro02)
#和使用的jdk的路径有关 include_directories(E:/Users/19318/.jdks/corretto-1.8.0_322-1/include) include_directories(E:/Users/19318/.jdks/corretto-1.8.0_322-1/include/win32) include_directories(E:/Users/19318/.jdks/corretto-1.8.0_322-1/include/win32/bridge)
set(CMAKE_CXX_STANDARD 14)
#add_executable:生成一个可执行文件 不添加则无法再clion中运行 add_executable(pro02 com_test_Main.cpp com_test_Main.h) #add_library:生成一个库 #sum:是生成共享库的名字,前面会自动加上lib前缀,如这里windows生成的是 libsum.dll #SHARED:库的类型为动态,windows上生成.dll,而STATIC 则是生成静态库,windows生成.a文件 add_library(sum SHARED com_test_Main.cpp)
|
再将jni下的头文件复制到c++项目下:

认识一下引用类型对照表:

接下来可以开始编写程序了:
1 2 3 4 5 6 7 8 9
| #include <jni.h> #include "com_test_Main.h"
JNIEXPORT jint JNICALL Java_com_test_Main_sum (JNIEnv *, jclass, jint a, jint b) { return a+b; }
|
接着我们就可以将cpp编译为动态链接库,在Windows下应该生成.dll文件
直接运行项目,我们可以在cmake-build-debug文件夹下找到生成的dll文件

注意这里运行时会报错undefined reference to ‘WinMain’,因为我们的项目没有main函数,但报错并不影响dll文件的生成和使用。
将生成的dll文件加载到Java程序中,运行即可得到结果。
1 2 3 4 5 6 7 8 9 10 11
| public class Main { static { System.load("D:\\C++\\pro02\\cmake-build-debug\\libsum.dll"); } public static void main(String[] args) { System.out.println(sum(1,2)); }
public static native int sum(int a,int b); }
|