Java 基础教程

Java 面向对象

Java 高级教程

Java 笔记

Java FAQ

java jni调用


在 Java 中,JNI(Java Native Interface)用于在 Java 代码中调用本地(Native)代码,通常是 C 或 C++代码。以下是几种使用 JNI 的常见方式,每种方式都包括步骤流程和相应的示例代码。

方法一:手动编写 JNI 代码

步骤流程:

  1. 编写 Java 类和本地库接口。
  2. 使用 javac 编译 Java 类生成 .class 文件。
  3. 使用 javah 生成 C/C++头文件。
  4. 实现 C/C++本地库,编译成动态链接库(.dll.so 等)。
  5. 在 Java 中加载本地库,调用本地方法。

示例代码:

创建 Java 类(HelloJNI.java):

public class HelloJNI {
    static {
        System.loadLibrary("hello"); // 加载本地库
    }

    public native void sayHello(); // 声明本地方法
}

编译 Java 类并生成.class 文件:

javac HelloJNI.java

使用 javah 生成头文件(命令需在类文件所在目录执行):

javah HelloJNI

实现 C/C++本地库(hello.cpp):

#include <jni.h>
#include "HelloJNI.h"

JNIEXPORT void JNICALL Java_HelloJNI_sayHello(JNIEnv *env, jobject obj) {
    printf("Hello from C++!\n");
}

编译生成动态链接库(示例使用 Linux 为例,其他平台类似):

g++ -shared -o libhello.so -I${JAVA_HOME}/include -I${JAVA_HOME}/include/linux hello.cpp

在 Java 中调用本地方法:

public class Main {
    public static void main(String[] args) {
        HelloJNI hello = new HelloJNI();
        hello.sayHello();
    }
}

方法二:使用 SWIG(Simplified Wrapper and Interface Generator)

步骤流程:

  1. 编写接口定义文件(.i )。
  2. 使用 SWIG 生成 JNI 封装代码。
  3. 实现 C/C++本地库,编译成动态链接库。
  4. 在 Java 中调用生成的封装类。

示例代码:

编写接口定义文件(hello.i):

%module hello
%{
#include "hello.h"
%}
%include "hello.h"

使用 SWIG 生成 JNI 封装代码:

swig -java -c++ -outdir generated -o hello_wrap.cpp hello.i
  1. 实现 C/C++本地库同样按照第一种方法进行。
  2. 在 Java 中调用生成的封装类:
public class Main {
    public static void main(String[] args) {
        Hello hello = new Hello();
        hello.sayHello();
    }
}

方法三:使用 JNA(Java Native Access)

步骤流程:

  1. 创建 Java 接口并继承 com.sun.jna.Library
  2. 使用 JNA 加载本地库。
  3. 定义本地方法。
  4. 在 Java 中调用本地方法。

示例代码:

创建 Java 接口(HelloJNA.java):

import com.sun.jna.Library;
import com.sun.jna.Native;

public interface HelloJNA extends Library {
    HelloJNA INSTANCE = Native.load("hello", HelloJNA.class);

    void sayHello();
}

在 Java 中调用本地方法:

public class Main {
    public static void main(String[] args) {
        HelloJNA.INSTANCE.sayHello();
    }
}

依赖坐标:

Maven:

<dependency>
    <groupId>net.java.dev.jna</groupId>
    <artifactId>jna</artifactId>
    <version>5.10.0</version>
</dependency>

Gradle:

implementation 'net.java.dev.jna:jna:5.10.0'

请注意,每种方法都有其适用的场景和优缺点。选择最适合你需求的方法,然后根据上述步骤进行实现。上述示例中的库名、文件名等可能需要根据你的项目结构进行调整。

在Java中使用JNI调用DLL(DynamicLinkLibrary)可以实现与底层C/C++代码的交互。java):编译和运行:##使用 ...
在Java中进行异步调用有多种方式,我将为您介绍几种常见的实现方式,包括使用Java原生的方式以及一些常用的第三方库。示例代码:Maven依 ...
在Java中使用gRPC进行调用有几种不同的方式,我会为你介绍其中的两种主要方式:使用原生的gRPC库和使用SpringBoot集成的方式。 ...
在Java中进行异步调用方法有多种方式,我将为您介绍几种常见的实现方式,包括使用原生Java、Java线程池、CompletableFutu ...
###直接调用Python脚本这种方式是最简单直接的方式,可以在Django视图函数中直接调用Python脚本文件。你可以在Django的视 ...