在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头文件。以下是你需要遵循的步骤:
- 编写java类
- 编译java类,使用javac命令编译Java源文件。这一步骤会生成.class文件,javah工具需要这些文件才能工作。如,javac org/example/MyClass.java,注意.java文件所在的路径
- 使用javah生成C头文件,需要指定类的全限定名(包括包名)。如,javah -jni org.example.MyClass
- 生成.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/include−IJAVA_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 ***包
结果类似如下
 


















