c语言jni实战,双系统
1.首次编写jni接口代码,需要安装java
#centos ,我使用的centos,其他系统安装方式不同。
sudo yum update -y
sudo yum install java-11-openjdk-devel -y
java -version
#输出版本类似
#openjdk version "1.8.0_292"
#OpenJDK Runtime Environment (build 1.8.0_292-b10)
#OpenJDK 64-Bit Server VM (build 25.292-b10, mixed mode)
vi /etc/profile.d/java.sh
增加
export JAVA_HOME=/usr/lib/jvm/java-11-openjdk
export JRE_HOME=$JAVA_HOME/lib
export PATH=$JAVA_HOME/bin:$PATH
#windows
①安装jdk,去java官网下载,这里使用版本jdk-23_windows-x64_bin.exe
②安装完毕后设置环境变量
新建系统变量 JAVA_HOME:C:\Program Files\Java\jdk-23
是你jdk的安装路径,默认是这个
③在环境变量的PATH中新增 %JAVA_HOME%\bin
④重启计算机或visual studio
2.配置jni环境变量(linux接第一步)
find /usr/lib/jvm -name jni.h
#/usr/lib/jvm/java-11-openjdk-11.0.23.0.9-2.el7_9.x86_64
vi ~/.bashrc
#在末尾加入
export JAVA_HOME=/usr/lib/jvm/java-11-openjdk-11.0.23.0.9-2.el7_9.x86_64
export C_INCLUDE_PATH=$JAVA_HOME/include:$JAVA_HOME/include/linux:$C_INCLUDE_PATH
保存后重启机器
LinuxMakefile
# JDK 安装路径
JDK_PATH ?= $(shell echo $$JAVA_HOME)
# 编译器和标志
CC = gcc
CFLAGS = -shared -fPIC -std=c99 -D_GNU_SOURCE
JNI_INCLUDE = -I$(JDK_PATH)/include -I$(JDK_PATH)/include/linux
#JNI_INCLUDE_LINUX = $(JDK_PATH)/include/linux
COMM_INC_BASE = ../common
GLIB_INC_BASE = -I./ -I../common/glib_include/glib-2.0/ -I../common/glib_include/glib-2.0/glib/ \
-I../common/glib_include/glib-2.0/include/ -I../common/gmssl_include/
INCLUDE_PATH = $(JNI_INCLUDE) $(GLIB_INC_BASE)
# 目标文件和库文件
TARGET = libzcopy
LIBRARY = ../bin/libzcopy.so # 修改为将生成文件放到 ../bin 目录
# 默认目标:编译共享库
$(LIBRARY): com_hess_jni_zcopy_HessZcopy.c ../common/log.c hess_jni_zcopy.c ../common/tools.c ../common/cjson/cJSON.c
$(shell mkdir -p ../bin) # 确保 ../bin 目录存在
$(CC) $(CFLAGS) $(INCLUDE_PATH) -o $(LIBRARY) $^
# 清理生成的文件
clean:
rm -f $(LIBRARY)
.PHONY: clean
Windows配置
- 预处理器JNI_EXPORTS
- 附加包含目录$(JAVA_HOME)\include
- $(JAVA_HOME)\include\win32
- 附加库目录
- $(JAVA_HOME)\lib
- 输入jvm.lib
项目代码,只记录接口部分
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_hess_jni_zcopy_HessZcopy */
#ifndef _Included_com_hess_jni_zcopy_HessZcopy
#define _Included_com_hess_jni_zcopy_HessZcopy
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_hess_jni_zcopy_HessZcopy
* Method: status
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_hess_jni_zcopy_HessZcopy_status
(JNIEnv *, jobject);
/*
* Class: com_hess_jni_zcopy_HessZcopy
* Method: config
* Signature: (Ljava/lang/String;)Z
*/
JNIEXPORT jboolean JNICALL Java_com_hess_jni_zcopy_HessZcopy_config
(JNIEnv *, jobject, jstring);
/*
* Class: com_hess_jni_zcopy_HessZcopy
* Method: configWithFile
* Signature: (Ljava/lang/String;)Z
*/
JNIEXPORT jboolean JNICALL Java_com_hess_jni_zcopy_HessZcopy_configWithFile
(JNIEnv *, jobject, jstring);
/*
* Class: com_hess_jni_zcopy_HessZcopy
* Method: start
* Signature: ()Z
*/
JNIEXPORT jboolean JNICALL Java_com_hess_jni_zcopy_HessZcopy_start
(JNIEnv *, jobject,
jint sync_type, jstring source,
jstring dest, jstring confpath);
/*
* Class: com_hess_jni_zcopy_HessZcopy
* Method: stop
* Signature: ()Z
*/
JNIEXPORT jboolean JNICALL Java_com_hess_jni_zcopy_HessZcopy_stop
(JNIEnv *, jobject);
/*
* Class: com_hess_jni_zcopy_HessZcopy
* Method: diff file start
* Signature: ()Z
* param: diff_rule use bitmap,"ct" 1, "ch" 2, "cs" 4, "ca" 8, "co" 16
*/
JNIEXPORT jboolean JNICALL Java_com_hess_jni_zcopy_HessZcopy_diffstart
(JNIEnv *, jobject, jint diff_rule, jint max_num, jstring source, jstring dest);
/*
* Class: com_hess_jni_zcopy_HessZcopy
* Method: diff file stop
* Signature: ()Z
*/
JNIEXPORT jboolean JNICALL Java_com_hess_jni_zcopy_HessZcopy_diffstop
(JNIEnv *, jobject);
/*
* Class: com_hess_jni_zcopy_HessZcopy
* Method: init
* Signature: ()Z
*/
JNIEXPORT jboolean JNICALL Java_com_hess_jni_zcopy_HessZcopy_init
(JNIEnv *, jobject);
/*
* Class: com_hess_jni_zcopy_HessZcopy
* Method: uninit
* Signature: ()Z
*/
JNIEXPORT jboolean JNICALL Java_com_hess_jni_zcopy_HessZcopy_uninit
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
#include "com_hess_jni_zcopy_HessZcopy.h"
#include "../common/log.h"
#include "../common/ztype.h"
#include "../common/tools_third.h"
#include "../common/tools.h"
#include "hess_jni_zcopy.h"
#include <string.h>
#include <stdlib.h>
char g_ctl_path[ZMAX_PATH] = {0};
#ifdef _MSC_VER
bool g_is_xp = false;
#endif
bool g_kill_needed = false;
const char* jstringToChar(JNIEnv *env, jstring jstr)
{
if (jstr == NULL)
return NULL;
return (*env)->GetStringUTFChars(env, jstr, NULL);
}
// 辅助函数:抛出Java异常
static void throwJavaException(JNIEnv *env, const char *message)
{
jclass exceptionClass = (*env)->FindClass(env, "java/lang/Exception");
if (exceptionClass != NULL) {
(*env)->ThrowNew(env, exceptionClass, message);
}
(*env)->DeleteLocalRef(env, exceptionClass);
}
JNIEXPORT jstring JNICALL Java_com_hess_jni_zcopy_HessZcopy_status(JNIEnv *env, jobject obj)
{
// TODO: 实现获取实际状态的逻辑
char *task_status_res = malloc(BUFFER_SIZE);
log_info(__FILE__, __LINE__, "get_task_status start");
int res = get_task_status(task_status_res, g_ctl_path);
log_info(__FILE__, __LINE__, "get_task_status end res:%d task_status_res:%s", res, task_status_res);
jstring status_res = (*env)->NewStringUTF(env, task_status_res);
free(task_status_res);
return status_res;
}
JNIEXPORT jboolean JNICALL Java_com_hess_jni_zcopy_HessZcopy_config(JNIEnv *env, jobject obj, jstring jsonConfig)
{
if (jsonConfig == NULL)
{
throwJavaException(env, "Config JSON string cannot be null");
return JNI_FALSE;
}
const char *json_conf = (*env)->GetStringUTFChars(env, jsonConfig, NULL);
if (json_conf == NULL)
{
throwJavaException(env, "Failed to get config string");
return JNI_FALSE;
}
char *hotupdate_res = malloc(BUFFER_SIZE);
log_info(__FILE__, __LINE__, "hotupdate_res start");
int res = zcopy_hotupdate(hotupdate_res, g_ctl_path, json_conf);
log_info(__FILE__, __LINE__, "hotupdate_res end res:%d , string:%s", res, hotupdate_res);
free(hotupdate_res);
(*env)->ReleaseStringUTFChars(env, jsonConfig, json_conf);
return res == E_CTL_CMD_RES_SUCCESS;
}
JNIEXPORT jboolean JNICALL Java_com_hess_jni_zcopy_HessZcopy_configWithFile(JNIEnv *env, jobject obj, jstring configFilePath)
{
if (configFilePath == NULL)
{
throwJavaException(env, "Config file path cannot be null");
return JNI_FALSE;
}
const char *filePath = (*env)->GetStringUTFChars(env, configFilePath, NULL);
if (filePath == NULL)
{
throwJavaException(env, "Failed to get file path string");
return JNI_FALSE;
}
printf("Java_com_hess_jni_zcopy_HessZcopy_configWithFile!\n");
// TODO: 实现文件配置处理逻辑
jboolean success = JNI_TRUE;
(*env)->ReleaseStringUTFChars(env, configFilePath, filePath);
return success;
}
JNIEXPORT jboolean JNICALL Java_com_hess_jni_zcopy_HessZcopy_start(JNIEnv *env, jobject obj,
jint sync_type, jstring source,
jstring dest, jstring confpath)
{
// TODO: 实现启动逻辑
log_info(__FILE__, __LINE__, "zcopy_task_start sync_type %d", sync_type);
if (sync_type > E_COPY_TYPE_END || sync_type < E_COPY_TYPE_REPRINT)
{
throwJavaException(env, "cmd error");
return JNI_FALSE;
}
char *task_status_res = malloc(BUFFER_SIZE);
const char *sourcec = jstringToChar(env, source);
const char *destc = jstringToChar(env, dest);
const char *confpathc = jstringToChar(env, confpath);
log_info(__FILE__, __LINE__, "zcopy_task_start start");
int res = zcopy_task_start(task_status_res, g_ctl_path, sync_type, sourcec, destc, confpathc);
log_info(__FILE__, __LINE__, "zcopy_task_start end res:%d , string:%s", res, task_status_res);
free(task_status_res);
(*env)->ReleaseStringUTFChars(env, source, sourcec);
(*env)->ReleaseStringUTFChars(env, dest, destc);
(*env)->ReleaseStringUTFChars(env, confpath, confpathc);
return res == E_CTL_CMD_RES_SUCCESS;
}
JNIEXPORT jboolean JNICALL Java_com_hess_jni_zcopy_HessZcopy_stop(JNIEnv *env, jobject obj)
{
// TODO: 实现停止逻辑
char *task_stop_res = malloc(BUFFER_SIZE);
log_info(__FILE__, __LINE__, "zcopy_task_stop start");
int res = zcopy_task_stop(task_stop_res, g_ctl_path);
log_info(__FILE__, __LINE__, "zcopy_task_stop end res:%d , string:%s", res, task_stop_res);
free(task_stop_res);
return res == E_CTL_CMD_RES_SUCCESS;
}
JNIEXPORT jboolean JNICALL Java_com_hess_jni_zcopy_HessZcopy_diffstart(JNIEnv *env, jobject obj, jint diff_rule,
jint max_num, jstring source, jstring dest)
{
return JNI_FALSE;
}
JNIEXPORT jboolean JNICALL Java_com_hess_jni_zcopy_HessZcopy_diffstop(JNIEnv *env, jobject obj)
{
return JNI_FALSE;
}
JNIEXPORT jboolean JNICALL Java_com_hess_jni_zcopy_HessZcopy_init(JNIEnv *env, jobject obj)
{
#ifdef _MSC_VER
g_is_xp = is_xp();
#endif
jboolean success = JNI_TRUE;
char log_path[ZMAX_PATH] = {0};
get_process_path(g_ctl_path, ZMAX_PATH);
sprintf_s(log_path, ZMAX_PATH, "%s%s", g_ctl_path, LOG_PATH);
log_init(log_path, 0);
strcat(g_ctl_path, CTL_PATH);
return success;
}
JNIEXPORT jboolean JNICALL Java_com_hess_jni_zcopy_HessZcopy_uninit(JNIEnv *env, jobject obj)
{
jboolean success = JNI_TRUE;
return success;
}
windows使用ms visual stdio