概述
- 目的: java类调用C语言
- 准备: jdk环境配置, gcc
- 环境:
操作系统: CentOS Linux release 7.6.1810 (Core)
GLIBC版本: 2.17
JDK版本: 1.8
编写Java类, 定义调用接口
- vim FirstJNI.java :
package com;
public class FirstJNI {
static{
try{
/*加载C语言动态库: 目录名可以自定义*/
System.load("/root/jnilibs/libFirstJNI.so");
}
catch(UnsatisfiedLinkError e){
System.out.println("Error Message:" + e.getMessage());
}
}
/*自定义调用方法echoString(): 将一个string参数打印到终端*/
public native void echoString(String str);
/*main方法测试:*/
public static void main(String[] args) {
String str = "Hello World!";
new FirstJNI().echoString(str);
}
}
- 编译生成class : javac FirstJNI.java
当前目录下会生成 FirstJNI.class,
由于java文件中定义了一个包名,
所以需在当前目录下新建一个以包名命名的目录, 并将class移至该目录
移动好以后目录结构如下:
调用接口的C语言实现
- 生成接口头文件: javah com.FirstJNI
当前目录下会生成: com_FirstJNI.h - 编辑C文件: vim FirstJNI.c
#include "com_FirstJNI.h"
/*
*接口声明来自: com_FirstJNI.h, 必须与头文件保持一致
*且需要加上形参名
*/
JNIEXPORT void JNICALL Java_com_FirstJNI_echoString
(JNIEnv * env, jobject obj, jstring str)
{
/*字符串类型转换*/
const char* p_str = (*env)->GetStringUTFChars(env, str, JNI_FALSE);
/*自定义C语言代码*/
printf("Recv String:%s\n", p_str);
/*释放资源*/
(*env)->ReleaseStringUTFChars(env, str, p_str);
return;
}
编译生成so
- vim makefile:
#定义JAVA_HOME变量, 以实际路径为准
JAVA_HOME=/usr/java/jdk1.8.0_201-amd64
all: FirstJNI.c
gcc -I$(JAVA_HOME)/include/linux/ -I$(JAVA_HOME)/include/ \
-fPIC -shared FirstJNI.c -o libFirstJNI.so
- 保存makefile运行命令: make
测试
-
将生成的 libFirstJNI.so 移至JAVA类中加载so的路径下:
cp libFirstJNI.so /root/jnilibs/ -
在编译目录下运行: java com.FirstJNI
结果如下图: