C/C++与Java混合的JNI编程 📅 2026/7/2 1:48:29 Java与JNI1.1. 什么是Java?Java是一种高级编程语言也是一个计算平台(通常指Java虚拟机)。最初由Sun Microsystems公司后被Oracle收购的James Gosling和他的团队在1995年发布。Java语言的设计目标是简单性、健壮性和跨平台兼容性。以下是Java的一些关键特点面向对象Java是一种面向对象的语言这意味着它基于对象和类的概念。对象代表现实世界中的实体或概念而类是创建对象的模板。平台无关性Java的一个核心特性是“一次编写到处运行”Write Once, Run AnywhereWORA。Java程序在执行前会被编译成字节码这种中间形式的代码可以在任何安装了Java虚拟机JVM的设备上运行。自动内存管理Java提供了自动垃圾回收机制这意味着程序员不需要手动管理内存的分配和释放从而减少了内存泄漏和其他内存相关错误。丰富的标准库Java拥有一个庞大的标准库也称为Java API提供了大量预先构建的类和接口用于处理文件输入/输出、网络编程、多线程编程、数据结构等。跨平台兼容性Java不仅可以在不同的操作系统上运行还可以在嵌入式系统、移动设备和大型服务器上运行。Java的应用场景广泛是目前最流行的后端系统开发语言此外Java还是Android系统的主要编程语言绝大部分的Android应用程序都基于Java语言进行开发。1.2. 什么是JVM?JVM(Java Virtual Machine)是一个可以执行Java字节码的虚拟计算机。它是Java平台的核心组成部分提供了Java程序运行所需的环境。JVM是Java语言能做到“一次编写到处运行”的基础。以下是JVM的一些关键特点和功能平台无关性JVM的主要目的是实现Java的跨平台特性。Java源代码被编译成平台无关的字节码这些字节码可以在任何安装了相应JVM的设备上运行。字节码解释器JVM包含一个字节码解释器它负责将字节码转换为特定平台的机器码。这个过程使得Java程序可以在不同的操作系统和硬件上运行。即时编译器JIT为了提高性能现代JVM通常包含一个即时编译器。JIT编译器会将热点代码频繁执行的代码编译成优化的机器码以提高执行效率。垃圾回收JVM负责管理内存分配和回收。它提供了自动垃圾回收机制帮助程序员管理内存减少内存泄漏和其他内存相关错误。安全沙箱JVM提供了一个安全的执行环境可以限制代码对系统资源的访问。这有助于防止恶意代码对系统造成破坏。类加载器JVM包含一个类加载器子系统负责动态加载、验证和准备类文件以供执行。类加载器确保类文件的完整性和安全性。本地接口JVM提供了与本地库交互的接口如JNIJava Native Interface允许Java代码调用本地代码C/C等以实现特定功能或性能优化。多线程支持JVM支持多线程执行允许程序同时执行多个任务。1.3. 什么是JNI?JNI(Java Native Interface)是一个允许Java代码与本地代码(如C/C)进行交互的接口。通过JNIJava应用程序可以调用本地库中的函数也可以被本地代码调用它是实现Java与C/C混合编程的关键机制。JNI主要包含以下两部分内容Java代码与本地代码交互的接口。支持JNI开发的一套开发工具如javah、javac等。JNI接口的官方文档https://docs.oracle.com/en/java/javase/21/docs/specs/jni/index.html1.4. 环境说明本章所有的示例代码的开发环境如下操作系统: Ubuntu 24.04JDK版本 21.0.5GCC版本 13.3.0开发工具VSCode2. 开发环境搭建2.1. Windows在官网下载最新版本的安装包官网下载地址https://www.oracle.com/cn/java/technologies/downloads/双击安装包根据提示一步步安装即可。打开命令行输入一下命令验证是否安装成功如果有显示相应的版本号则说明安装成功。java -version2.2. Linux(Ubuntu)安装JDK:# 1. 更新软件包列表sudo apt update# 3. 该命令将自动选择并安装最新的 LTS 版本当前是 OpenJDK 21[5]。sudo apt install default-jdk# 3. 验证是否安装成功如果有显示相应的版本号则说明安装成功。java --version设置环境变量# 1. 查找JDK的安装路径update-alternatives --config javaThere are 2 choices for the alternative java (providing /usr/bin/java).Selection Path Priority Status------------------------------------------------------------* 0 /usr/lib/jvm/java-21-openjdk-amd64/bin/java 2111 auto mode1 /usr/lib/jvm/java-11-openjdk-amd64/bin/java 1111 manual mode# 2. vim打开.zshrc(如果你的SHELL用的是.bashrc替换成相应的.bashrc)vim ~/.zshrc# 3. 在文件末尾添加如下内容export JAVA_HOME/usr/lib/jvm/java-21-openjdk-amd64export PATH${JAVA_HOME}/bin:${PATH}# 4. 重新加载配置source ~/.zshrc2.3. macOS以下是通过Homebrew工具的安装步骤确保已经安装Homebrew。# 1. 更新软件包列表brew update# 2.1 安装Oracle JDK的最新版本brew install oracle-jdk# 2.2 安装Open JDK的最新版本brew install java# 3. 验证是否安装成功如果有显示相应的版本号则说明安装成功。java --version2.4. Open JDK与Oracle JDKJava语言最初由Sun公司研发并发布了Java SE(Standard Edition)的规范和开源的Open JDK。Sun公司后被Oracle公司收购Oracle基于Open JDK开发了Oracle JDK。Open JDK是一个完全开源的项目遵循GPL v2许可。任何人都可以下载、使用、修改和分发它的代码。主要的Linux发行版(如FedoraUbuntu等)提供OpenJDK作为默认的Java SE实现。Oracle JDK则基于Open JDK构建但包含一些闭源组件如Java插件、Java WebStart的实现和一些第三方组件。这些组件包括了一些商业功能未开源。Open JDK和Oracle JDK都遵循Java SE的规范只是Oracle JDK提供了更多商业版的未开源的功能。3.Say Hello程序3.1. 新建SayHello.java新建一个say_hello的测试目录然后在该目录下新建一个SayHello.java文件并编写如下代码public class SayHello {// 类方法private native void sayHello(String name);// 静态方法private static native void sayGoodbye(String name);static {// 在程序初始化时加载native动态库(libhello.so)System.loadLibrary(hello);}public static void main(String[] args) {new SayHello().sayHello(Spencer);SayHello.sayGoodbye(陌尘);}}说明这里有两个被声明为native的方法表示这两个方法需要native代码(C/C)实现。这里一个是普通的类成员方法一个是静态的类方法。private native void sayHello(String name);private static native void sayGoodbye(String name);static包含的代码块表示在程序初始化时加载native动态库(libhello.so)static {System.loadLibrary(hello);}3.2. 编译SayHello.javajavac ./SayHello.java执行完成后会生成一个SayHello.class的字节码文件。3.3. 生成SayHello.h执行以下命令生成native代码的头文件# JDK 9.0 之前javah -cp ./ -d ./ SayHello# -cp ./表示设置classpath为当前目录在当前目录下查找.class文件# -d ./表示设置头文件的输出目录为当前目录# JDK 9.0 及之后javac -h ./ ./SayHello.java# 第一个./ 表示设置头文件的输出目录为当前目录执行成功后会在当前目录下生成SayHello.h头文件内容如下/* DO NOT EDIT THIS FILE - it is machine generated */#include jni.h/* Header for class SayHello */#ifndef _Included_SayHello#define _Included_SayHello#ifdef __cplusplusextern C {#endif/** Class: SayHello* Method: sayHello* Signature: (Ljava/lang/String;)V*/JNIEXPORT void JNICALL Java_SayHello_sayHello(JNIEnv *, jobject, jstring);/** Class: SayHello* Method: sayGoodbye* Signature: (Ljava/lang/String;)V*/JNIEXPORT void JNICALL Java_SayHello_sayGoodbye(JNIEnv *, jclass, jstring);#ifdef __cplusplus}#endif#endif代码说明