【JNI入门】Linux下 JNI 调用C语言, 编译及测试全过程

概述

  • 目的: 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移至该目录
    移动好以后目录结构如下:
    【JNI入门】Linux下 JNI 调用C语言, 编译及测试全过程

调用接口的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
    结果如下图:
    【JNI入门】Linux下 JNI 调用C语言, 编译及测试全过程