> 技术文档 > java 调用DLL动态库(附带源码)_java调用dll动态库

java 调用DLL动态库(附带源码)_java调用dll动态库


Java 调用 DLL 动态库

1. 项目背景

在 Windows 平台上,很多底层库或第三方 API 以 DLL(Dynamic Link Library,动态链接库) 形式提供。Java 本身不能直接调用 DLL,需要使用 JNI(Java Native Interface,Java 本地接口)JNA(Java Native Access) 进行调用。

本项目主要介绍 如何使用 Java 调用 DLL 文件,并提供 JNI 和 JNA 两种方式 的实现,帮助你根据需求选择合适的方法。


2. 相关知识

2.1 什么是 DLL?

  • DLL(Dynamic Link Library,动态链接库) 是 Windows 操作系统中的共享库,多个程序可以动态加载 DLL 以实现代码复用。
  • DLL 里面通常包含 函数、类、资源等,可用于扩展软件功能。

2.2 Java 如何调用 DLL?

Java 不能直接调用 C/C++ 编写的 DLL,需要借助:

  1. JNI(Java Native Interface)
    • 需要编写 C/C++ 代码 作为中间层,与 Java 交互。
    • 适用于 高性能、复杂逻辑场景,但开发复杂。
  2. JNA(Java Native Access)
    • 不需要写 C/C++,直接使用 Java 代码调用 DLL。
    • 适用于 简单 API 调用,但性能略逊于 JNI。

2.3 使用场景

方式 适用场景 复杂度 性能 JNI 需要高性能、复杂 C++ 交互 高 高 JNA 直接调用简单 DLL 函数 低 较高

3. 实现思路

我们将分别使用 JNI 和 JNA 来调用 DLL:

3.1 JNI 方式

  1. 编写 Java 代码 声明本地方法。
  2. 使用 javac 生成 .class 文件,然后用 javah 生成 C 头文件。
  3. 编写 C/C++ 代码 实现 DLL 逻辑。
  4. 编译生成 DLL,让 Java 调用它。

3.2 JNA 方式

  1. 使用 JNA 库,定义接口映射 DLL 方法。
  2. 直接调用 DLL,无需额外编写 C 代码。

4. 代码实现

4.1 使用 JNI 调用 DLL

(1)编写 Java 代码
public class JniExample { // 声明本地方法,调用 DLL 中的 nativeMethod public native String nativeMethod(String input); static { System.loadLibrary(\"MyLibrary\"); // 加载 DLL } public static void main(String[] args) { JniExample example = new JniExample(); String result = example.nativeMethod(\"Hello JNI!\"); System.out.println(\"Native Method Returned: \" + result); }}

 

注意System.loadLibrary(\"MyLibrary\") 加载的 DLL 名称是 MyLibrary.dll


(2)生成 C 头文件

编译 Java 代码:

javac JniExample.java

生成 JNI 头文件:

javah -jni JniExample

此时会生成 JniExample.h,内容如下:

/* DO NOT EDIT THIS FILE - it is machine generated */#include #ifndef _Included_JniExample#define _Included_JniExample#ifdef __cplusplusextern \"C\" {#endif/* * Class: JniExample * Method: nativeMethod * Signature: (Ljava/lang/String;)Ljava/lang/String; */JNIEXPORT jstring JNICALL Java_JniExample_nativeMethod (JNIEnv *, jobject, jstring);#ifdef __cplusplus}#endif#endif
(3)编写 C 代码

创建 JniExample.c

#include \"JniExample.h\"#include #include JNIEXPORT jstring JNICALL Java_JniExample_nativeMethod(JNIEnv *env, jobject obj, jstring input) { const char *inCStr = (*env)->GetStringUTFChars(env, input, NULL); char message[256] = \"JNI Received: \"; strcat(message, inCStr); (*env)->ReleaseStringUTFChars(env, input, inCStr); return (*env)->NewStringUTF(env, message);}
(4)编译并生成 DLL

使用 GCC(MinGW)或 MSVC 进行编译:

gcc -shared -o MyLibrary.dll -I\"%JAVA_HOME%\\include\" -I\"%JAVA_HOME%\\include\\win32\" JniExample.c -Wl,--add-stdcall-alias


(5)运行 Java 代码

java JniExample

输出:

Native Method Returned: JNI Received: Hello JNI!


4.2 使用 JNA 调用 DLL

(1)编写 C 代码

创建 SimpleLibrary.c

#include __declspec(dllexport) int add(int a, int b) { return a + b; }

编译生成 DLL:

gcc -shared -o SimpleLibrary.dll SimpleLibrary.c


(2)编写 Java 代码
import com.sun.jna.Library;import com.sun.jna.Native;public class JnaExample { // 定义接口,映射 DLL public interface SimpleLibrary extends Library { SimpleLibrary INSTANCE = Native.load(\"SimpleLibrary\", SimpleLibrary.class); int add(int a, int b); } public static void main(String[] args) { int result = SimpleLibrary.INSTANCE.add(5, 10); System.out.println(\"Result from DLL: \" + result); }}

运行 Java 代码:

java -cp .;jna-5.12.1.jar JnaExample

输出:

Result from DLL: 15


5. 代码解读

JNI 方式

  • nativeMethod:Java 声明的本地方法,在 C 代码中实现。
  • javah 生成 C 头文件,用于 C 代码编写。
  • C 代码实现:使用 JNIEnv 处理字符串并返回新的字符串。

JNA 方式

  • 不需要写 C 代码,直接使用 JNA 绑定 DLL 并调用函数。
  • 适合简单的 DLL API 交互,例如调用 数值计算、设备控制等 DLL

6. 项目总结

方式 适用场景 复杂度 优势 劣势 JNI 复杂 C/C++ 库交互,高性能场景 高 速度快,可完全控制 需要编写 C 代码 JNA 调用简单 DLL API 低 代码少,易维护 性能稍逊 JNI

选择建议:

  • 需要高性能复杂交互,用 JNI
  • 只是 调用简单 DLL 函数,用 JNA

7. 结论

本项目展示了 JNI 和 JNA 调用 DLL 的实现,适用于 Java 需要调用 Windows 本地库的场景。