本文目录导读:

我来给您一个完整的JNI(Java Native Interface)案例,从Java调用C/C++代码。
项目结构
JNIDemo/
├── src/
│ └── com/example/
│ └── NativeDemo.java
├── native/
│ ├── native_demo.c
│ └── native_demo.h
└── lib/
步骤1:编写Java类
// NativeDemo.java
package com.example;
public class NativeDemo {
// 声明native方法
public native int add(int a, int b);
public native String greet(String name);
public native int[] sortArray(int[] array);
// 加载动态库
static {
System.loadLibrary("nativedemo");
}
public static void main(String[] args) {
NativeDemo demo = new NativeDemo();
// 测试加法
int sum = demo.add(10, 20);
System.out.println("10 + 20 = " + sum);
// 测试字符串处理
String greeting = demo.greet("小明");
System.out.println("Greeting: " + greeting);
// 测试数组排序
int[] array = {5, 3, 8, 1, 9, 2};
int[] sortedArray = demo.sortArray(array);
System.out.print("Sorted array: ");
for (int num : sortedArray) {
System.out.print(num + " ");
}
System.out.println();
}
}
步骤2:生成C头文件
编译Java文件并生成头文件:
# 编译Java文件 javac src/com/example/NativeDemo.java # 生成头文件 javah -jni -classpath src com.example.NativeDemo
生成的native_demo.h
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_example_NativeDemo */
#ifndef _Included_com_example_NativeDemo
#define _Included_com_example_NativeDemo
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_example_NativeDemo
* Method: add
* Signature: (II)I
*/
JNIEXPORT jint JNICALL Java_com_example_NativeDemo_add
(JNIEnv *, jobject, jint, jint);
/*
* Class: com_example_NativeDemo
* Method: greet
* Signature: (Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_example_NativeDemo_greet
(JNIEnv *, jobject, jstring);
/*
* Class: com_example_NativeDemo
* Method: sortArray
* Signature: ([I)[I
*/
JNIEXPORT jintArray JNICALL Java_com_example_NativeDemo_sortArray
(JNIEnv *, jobject, jintArray);
#ifdef __cplusplus
}
#endif
#endif
步骤3:实现C代码
// native_demo.c
#include <jni.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "native_demo.h"
// 实现加法
JNIEXPORT jint JNICALL Java_com_example_NativeDemo_add
(JNIEnv *env, jobject obj, jint a, jint b) {
printf("C: Adding %d + %d\n", a, b);
return a + b;
}
// 实现字符串处理
JNIEXPORT jstring JNICALL Java_com_example_NativeDemo_greet
(JNIEnv *env, jobject obj, jstring name) {
// 将Java字符串转换为C字符串
const char *nativeName = (*env)->GetStringUTFChars(env, name, NULL);
if (nativeName == NULL) {
return NULL; // 内存分配失败
}
printf("C: Greeting %s\n", nativeName);
// 创建新的字符串
char greeting[100];
snprintf(greeting, sizeof(greeting), "你好,%s!来自C的问候!", nativeName);
// 释放原始字符串
(*env)->ReleaseStringUTFChars(env, name, nativeName);
// 将C字符串转换为Java字符串并返回
return (*env)->NewStringUTF(env, greeting);
}
// 实现数组排序
JNIEXPORT jintArray JNICALL Java_com_example_NativeDemo_sortArray
(JNIEnv *env, jobject obj, jintArray array) {
// 获取数组长度
jsize length = (*env)->GetArrayLength(env, array);
// 获取数组元素
jint *elements = (*env)->GetIntArrayElements(env, array, NULL);
if (elements == NULL) {
return NULL; // 内存分配失败
}
printf("C: Sorting array of length %d\n", length);
// 打印原始数组
printf("Original array: ");
for (int i = 0; i < length; i++) {
printf("%d ", elements[i]);
}
printf("\n");
// 使用冒泡排序
for (int i = 0; i < length - 1; i++) {
for (int j = 0; j < length - 1 - i; j++) {
if (elements[j] > elements[j + 1]) {
int temp = elements[j];
elements[j] = elements[j + 1];
elements[j + 1] = temp;
}
}
}
// 创建新的Java数组
jintArray result = (*env)->NewIntArray(env, length);
if (result == NULL) {
(*env)->ReleaseIntArrayElements(env, array, elements, 0);
return NULL;
}
// 将排序后的数据设置到新数组
(*env)->SetIntArrayRegion(env, result, 0, length, elements);
// 释放原始数组
(*env)->ReleaseIntArrayElements(env, array, elements, 0);
return result;
}
步骤4:编译动态库
Linux/Mac系统:
# 编译C代码为动态库
gcc -shared -fPIC -I$JAVA_HOME/include -I$JAVA_HOME/include/linux \
-o lib/libnativedemo.so native/native_demo.c
Windows系统:
# 使用MinGW或Visual Studio
gcc -shared -I"%JAVA_HOME%\include" -I"%JAVA_HOME%\include\win32" \
-o lib\nativedemo.dll native\native_demo.c
Mac OS X系统:
gcc -shared -fPIC -I$JAVA_HOME/include -I$JAVA_HOME/include/darwin \
-o lib/libnativedemo.dylib native/native_demo.c
步骤5:运行程序
# 指定库路径并运行 java -Djava.library.path=lib -classpath src com.example.NativeDemo
完整构建脚本(build.sh)
#!/bin/bash
# 设置JAVA_HOME(根据自己的环境修改)
export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64
# 清理
rm -rf src/com/example/*.class
rm -rf lib/*.so lib/*.dylib
# 编译Java
echo "Compiling Java..."
javac src/com/example/NativeDemo.java
# 生成头文件
echo "Generating header file..."
javah -jni -classpath src com.example.NativeDemo
mv com_example_NativeDemo.h native/
# 编译C动态库
echo "Compiling C library..."
gcc -shared -fPIC -I$JAVA_HOME/include -I$JAVA_HOME/include/linux \
-o lib/libnativedemo.so native/native_demo.c
echo "Build complete!"
# 运行测试
echo "Running test..."
java -Djava.library.path=lib -classpath src com.example.NativeDemo
输出结果
C: Adding 10 + 20
10 + 20 = 30
C: Greeting 小明
Greeting: 你好,小明!来自C的问候!
C: Sorting array of length 6
Original array: 5 3 8 1 9 2
Sorted array: 1 2 3 5 8 9
关键概念解释
-
JNIEnv:代表JNI环境的指针,用于调用JNI函数
-
jobject:表示Java对象的引用
-
类型映射:
jint↔ Javaintjstring↔ JavaStringjintArray↔ Javaint[]
-
JNI函数:
GetStringUTFChars():获取Java字符串的C表示NewStringUTF():创建Java字符串GetIntArrayElements():获取Java数组的C表示ReleaseStringUTFChars():释放字符串资源
这个案例涵盖了JNI中最常见的操作:基本类型传递、字符串处理和数组操作。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播