java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Java JNI高级用法

Java JNI的高级用法示例详解

作者:猩火燎猿

JNI是Java高级应用中不可或缺的技术之一,它允许Java程序与本地代码进行交互,大大拓宽了Java应用的范围和性能,这篇文章主要介绍了Java JNI高级用法的相关资料,需要的朋友可以参考下

1. native 层多线程与 JVM 交互

1.1 native 层启动线程

在 JNI 中,native 层可以创建自己的线程(如 pthread、std::thread),但这些线程不是 JVM 线程,不能直接访问 JVM 资源。
必须 attach 到 JVM,才能安全调用 Java 对象或方法。

1.2 attach/detach 线程

JavaVM* jvm; // 全局保存 JavaVM 指针

// 线程函数
void* thread_func(void* arg) {
    JNIEnv* env;
    // 线程 attach 到 JVM
    (*jvm)->AttachCurrentThread(jvm, (void**)&env, NULL);

    // 可以安全访问 Java 对象和方法
    // ...

    // 线程结束前 detach
    (*jvm)->DetachCurrentThread(jvm);
    return NULL;
}

注意

1.3 native 层回调 Java(多线程)

2. 复杂对象的 JNI 传递与构造

2.1 Java 传对象给 native

Java:

public class Person {
    public int age;
    public String name;
}
public native void processPerson(Person p);

C:

jclass cls = (*env)->GetObjectClass(env, person);
jfieldID fid_age = (*env)->GetFieldID(env, cls, "age", "I");
jint age = (*env)->GetIntField(env, person, fid_age);

jfieldID fid_name = (*env)->GetFieldID(env, cls, "name", "Ljava/lang/String;");
jstring jname = (jstring)(*env)->GetObjectField(env, person, fid_name);
// 转换为 C 字符串
const char* cname = (*env)->GetStringUTFChars(env, jname, NULL);
// ...
(*env)->ReleaseStringUTFChars(env, jname, cname);

2.2 native 构造 Java 对象并返回

C:

jclass cls = (*env)->FindClass(env, "Person");
jmethodID ctor = (*env)->GetMethodID(env, cls, "<init>", "()V");
jobject obj = (*env)->NewObject(env, cls, ctor);

jfieldID fid_age = (*env)->GetFieldID(env, cls, "age", "I");
(*env)->SetIntField(env, obj, fid_age, 25);

// 返回 obj 给 Java
return obj;

2.3 复杂数组/集合的传递

3. Java Lambda 与 JNI

3.1 Java Lambda 本质

Lambda 是编译期自动生成的匿名类对象,实现了目标接口(如 Runnable、Function)。
JNI 层看到的是普通的 Java 对象。

3.2 JNI 层调用 Lambda

示例:

public native void useCallback(Runnable r);
useCallback(() -> System.out.println("Hello from Lambda!"));

C:

jclass cls = (*env)->GetObjectClass(env, runnable);
jmethodID mid = (*env)->GetMethodID(env, cls, "run", "()V");
(*env)->CallVoidMethod(env, runnable, mid);

3.3 局限与注意

4. JNI 性能基准测试与优化

4.1 性能测试方法

JMH 示例:

@Benchmark
public void testJavaAdd() {
    int a = 1, b = 2;
    int c = a + b;
}

@Benchmark
public void testJNIAdd() {
    nativeAdd(1, 2);
}

4.2 常见性能瓶颈

4.3 优化建议

5. 典型面试题与实战解析

6. native 层多线程最佳实践

6.1 多线程安全 attach/detach

示例:

JavaVM* g_jvm = NULL;

jint JNI_OnLoad(JavaVM* vm, void* reserved) {
    g_jvm = vm;
    return JNI_VERSION_1_6;
}

void* worker(void* arg) {
    JNIEnv* env;
    if ((*g_jvm)->AttachCurrentThread(g_jvm, (void**)&env, NULL) == 0) {
        // 使用 env 调用 Java 方法
        // ...
        (*g_jvm)->DetachCurrentThread(g_jvm);
    }
    return NULL;
}

6.2 并发安全的回调

7. 复杂对象高效传递与映射

7.1 批量数据结构传递

Java:

ByteBuffer buf = ByteBuffer.allocateDirect(1024);
nativeProcessBuffer(buf);

C:

void JNICALL nativeProcessBuffer(JNIEnv* env, jobject obj, jobject buffer) {
    void* ptr = (*env)->GetDirectBufferAddress(env, buffer);
    // 直接操作内存
}

7.2 复杂对象序列化

8. lambda 在高性能场景下的实战建议

8.1 场景分析

8.2 高效回调设计

9. JNI 性能基准测试与分析

9.1 JMH 基准测试示例

@Benchmark
public void javaMethod() {
    // 普通 Java 方法
}

@Benchmark
public void jniMethod() {
    nativeMethod();
}

@Benchmark
public void jniArrayMethod() {
    nativeArrayMethod(new int[1000]);
}

测试结论

9.2 优化建议

10. JNI 在实际项目中的架构建议

10.1 封装 native 层 API

10.2 资源和异常管理

10.3 跨平台适配

11. 典型面试题解析(补充)

11. 总结

到此这篇关于Java JNI的高级用法的文章就介绍到这了,更多相关Java JNI高级用法内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文