linux中Java程序调用C程序中方法的实现方式浅析

24 篇文章 2 订阅

在Linux中,Java程序可以通过JNI(Java Native Interface)来调用C程序的方法。

在这里插入图片描述在这里插入图片描述

Linux系统环境,Java调用C的主要流程如下:
1、创建Java类文件,如NativeLibrary.java
2、编写Java代码,加载.so共享库(C程序生成该名称的.so共享库),并声明本地方法
3、使用javac编译Java类,生成.class文件
4、使用javah对.class文件生成C头文件,该文件包含了Java和C之间通信所需的函数声明
5、创建C语言源文件,如NativeLibrary.c
6、编写C程序代码并实现要被Java调用的方法
7、使用gcc编译C程序和C头文件生成动态链接库(共享库.so文件)
8、运行Java程序,并调用C程序中的方法

1、Java类文件

创建NativeLibrary.java文件,内容如下:

public class NativeLibrary {
    static {
        System.loadLibrary("mylib"); // 加载名为"mylib"的共享库
    }
 
    public native void printHello(); // 声明本地方法
 
    public static void main(String[] args) {
        new Hello().printHello(); // 调用本地方法
    }
}

其中,System.loadLibrary(“mylib”);为加载共享库, public native void printHello();为声明本地方法。

在Java中,加载本地库(通常是C或C++编写的库,以.dll、.so或.dylib等形式存在)主要有两种方式:System.loadLibrary()和System.load()。这两种方法用于与Java Native Interface (JNI)交互,使Java程序能够调用本地代码。
使用 System.loadLibrary()允许Java运行时根据平台自动定位和加载本地库。你只需要提供库的名字(不包括扩展名,如.dll或.so),Java运行时会在标准位置搜索这些库。
使用 System.load()允许你直接指定本地库的完整路径。这在库不在标准位置或需要加载特定版本的库时非常有用。
当使用System.loadLibrary()时,通常需要在linux环境设置环境变量LD_LIBRARY_PATH,如export LD_LIBRARY_PATH=“.so文件所在路径”

2、C头文件

javah是Java的一个命令行工具,用于生成JNI(Java Native Interface)的C或C++头文件。这些头文件包含了Java方法的本地签名,允许C或C++代码调用这些方法。当你需要编写本地代码来实现Java方法时,javah生成的头文件是非常有用的。
假设你有一个Java类MyClass,它位于包org.example中,并且你想要为这个类生成JNI头文件。以下是你需要遵循的步骤:

  1. 编写java类
  2. 编译java类,使用javac命令编译Java源文件。这一步骤会生成.class文件,javah工具需要这些文件才能工作。如,javac org/example/MyClass.java,注意.java文件所在的路径
  3. 使用javah生成C头文件,需要指定类的全限定名(包括包名)。如,javah -jni org.example.MyClass
  4. 生成.h文件,如org_example_NativeLibrary.h

C头文件内容如下

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class org_example_NativeLibrary */

#ifndef _Included_org_example_NativeLibrary
#define _Included_org_example_NativeLibrary
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     org_example_NativeLibrary
 * Method:    printHello
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_org_example_NativeLibrary_printHello
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

3、C程序文件

创建C程序文件,如NativeLibrary.c,内容如

#include <jni.h>
#include "org_example_NativeLibrary.h"
 
JNIEXPORT void JNICALL Java_org_example_NativeLibrary_printHello(JNIEnv *env, jobject obj) {
    printf("Hello from C!\n");
}

其中,#include <jni.h>的jni.h文件来自jdk环境下,#include "NativeLibrary.h"来自使用javah生成的C头文件,Java_org_example_NativeLibrary_printHello需要和C头文件中的方法名称抱持一致。

4、共享库.so文件

编译C程序和头文件生成共享库,命令如下

gcc -shared -fpic -o libmylib.so -I$JAVA_HOME/include -I$JAVA_HOME/include/linux NativeLibrary.c

其中 libmylib.so为生成的共享库文件, -I J A V A H O M E / i n c l u d e − I JAVA_HOME/include -I JAVAHOME/includeIJAVA_HOME/include/linux为找C程序中的jni.h依赖,NativeLibrary.c为C程序文件,且C头文件需要和C程序文件在同一目录下。
在执行编译之前,请确保已经安装了gcc编译器,以及jdk环境。

5、运行Java程序

在linux环境中将.so共享库文件所在路径加入java.library.path中,设置环境变量,如下

export LD_LIBRARY_PATH=".so文件所在路径"
java ***类或java -jar ***包

结果类似如下
在这里插入图片描述

  • 23
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值