一、简介
Java是一种跨平台的编程语言,而C语言则是一种高效且广泛应用的编程语言。
它的跨平台特性是通过Java虚拟机(JVM)来实现的。虽然JVM的性能逐渐提升,但在某些场景下,使用C语言编写的代码可能仍然比Java代码更高效。
例如操作系统的API或硬件驱动程序。在这些情况下,我们需要使用C语言编写的代码来与系统资源进行交互。
说明:底层的系统资源只能通过java的本地方法才能访问
二、调用方法
Java提供了两种方式来调用C语言编写的代码:JNI(Java Native Interface)和JNA(Java Native Access)。
2.1 JNI
JNI是Java提供的标准接口,它允许Java代码通过本地方法接口(Native Method Interface)调用C语言代码。
通过JNI,我们可以在Java中声明本地方法,并使用Java的反射机制来调用这些本地方法。
工作流程

2.1.1 编写java本地方法
public class MyClass {
#本地方法
public native int add(int a, int b);
}
|
2.1.2 生成本地方法对应的头文件
#后面跟 输出目录 源文件地址 javac -encoding utf-8 -h . MyClass.java |
2.1.3 编写c语言测试代码
引入我们上面生成的.h 文件,开始编写C语言的代码,并将其编译成动态链接库(dll或so)供Java调用。
下面是一个简单的示例,展示了如何计算两个整数的和:
#include <stdio.h>
#include "MyClass.h"
#Java_com_example_MyClass_add是JNI函数命名的约定,它由Java类的全限定名和方法名组成。
JNIEXPORT jint JNICALL Java_com_example_MyClass_add(JNIEnv *env, jobject obj, jint a, jint b) {
return a + b;
}
|
编译文件,注意引入jdk头文件包下的jni.h等
gcc -fPIC -shared -I/usr/lib/jvm/jdk-17-oracle-x64/include -I/usr/lib/jvm/jdk-17-oracle-x64/include/linux -o libMyClass.so MyClass.c |
2.1.4 使用动态库
public class MyClass {
static {
#用于加载C语言编译的动态链接库
System.loadLibrary("mylib");
#System.load("mylib"); 如果是路径使用这种
}
public native int add(int a, int b);
public static void main(String[] args) {
MyClass myClass = new MyClass();
int result = myClass.add(1, 2);
System.out.println("Result: " + result);
}
}
|
2.2 JNA
与JNI相比,JNA提供了更简洁的API,并且不需要编写头文件或手动加载动态链接库。
JNA使用Java的动态代理机制,将C语言函数映射为Java接口的方法,从而实现在Java中调用C语言。
在使用JNA前,需要引入maven依赖
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna</artifactId>
<version>5.5.0</version>
</dependency>
|
2.2.1 准备一个动态链接库
#源文件内容
#include <stdio.h>
int test(char *input){
printf("input:%s\n",input);
return 0;
}
#生成动态链接库
gcc -fPIC -shared -o libtest.so test.c
|
2.2.2 继承Library接口调用
package jna;
import com.sun.jna.Library;
import com.sun.jna.Native;
/**
* 接口继承
*
* @author majun
* @version 1.0
* @since 2023-08-22 22:27
*/
public interface MyClibrary extends Library {
MyClibrary INSTANTCE = Native.load("/root/libtest.so", MyClibrary.class);
int test(String input);
//测试
public static void main(String[] args) {
int test = MyClibrary.INSTANTCE.test("extend Library");
System.out.println(test);
}
}
|
2.2.3 直接NativeLibrary.getInstance调用
import com.sun.jna.Function;
import com.sun.jna.NativeLibrary;
/**
* TODO
*
* @author majun
* @version 1.0
* @since 2023-03-31 7:44
*/
public class Main {
public static void main(String[] args) {
NativeLibrary instance = NativeLibrary.getInstance("/root/libtest.so");
Function func = instance.getFunction("test");
Object res = func.invoke(Integer.class, new Object[]{"NativeLibrary.getInstance"});
System.out.println( res);
}
}
|
309

被折叠的 条评论
为什么被折叠?



