JNI 面试题及答案

JNI 面试题及答案

JNI 基础概念

问题:什么是 JNI?它的作用是什么?

JNI(Java Native Interface)是 Java 本地接口,用于实现 Java 代码与其他语言(如 C/C++)的交互。它允许 Java 程序调用本地代码(Native Code),反之亦然。JNI 常用于性能优化、访问硬件或操作系统特性、复用现有本地库等场景。

问题:JNI 的优缺点是什么?

优点:

  • 可以调用本地代码,提升性能。
  • 访问系统级功能或硬件特性。
  • 复用已有的 C/C++ 库。

缺点:

  • 增加了复杂性,跨语言调用容易出错。
  • 破坏了 Java 的跨平台性。
  • 内存管理需手动处理,容易引发内存泄漏或崩溃。

JNI 开发流程

问题:如何实现一个简单的 JNI 调用?

  1. 在 Java 类中声明 native 方法:

    java 复制代码
    public class NativeDemo {
        public native void sayHello();
        static {
            System.loadLibrary("NativeDemo");
        }
    }
  2. 使用 javac 编译 Java 文件,生成 .class 文件。

  3. 使用 javah(或 javac -h)生成头文件(.h),包含 JNI 方法签名。

  4. 实现 C/C++ 代码,包含头文件并实现方法:

    c 复制代码
    #include <jni.h>
    #include "NativeDemo.h"
    JNIEXPORT void JNICALL Java_NativeDemo_sayHello(JNIEnv *env, jobject obj) {
        printf("Hello from JNI!\n");
    }
  5. 编译为动态库(.so.dll),并确保 Java 程序能加载该库。


JNI 数据类型与内存管理

问题:JNI 中如何表示 Java 的基本数据类型?

JNI 定义了与 Java 基本类型对应的本地类型:

  • jint(对应 int)、jlong(对应 long
  • jfloat(对应 float)、jdouble(对应 double
  • jboolean(对应 boolean)、jchar(对应 char

问题:JNI 如何处理 Java 对象?

通过 jobject 类型表示 Java 对象。

  • 局部引用(Local Reference):默认创建,需手动释放或依赖 JNI 环境自动回收。
  • 全局引用(Global Reference):显式创建(NewGlobalRef),需手动释放。
  • 弱全局引用(Weak Global Reference):不阻止垃圾回收,需检查是否有效。

JNI 异常处理

问题:JNI 中如何捕获和处理 Java 异常?

  • 检查异常:调用 JNI 函数后,使用 ExceptionCheckExceptionOccurred 检查是否有异常。
  • 抛出异常:通过 ThrowNew 抛出新的异常。
  • 清除异常:使用 ExceptionClear 清除当前异常。

示例代码:

c 复制代码
jclass clazz = (*env)->FindClass(env, "java/lang/NullPointerException");
if (clazz != NULL) {
    (*env)->ThrowNew(env, clazz, "Null pointer in JNI");
}

JNI 性能优化

问题:如何优化 JNI 调用的性能?

  • 减少 JNI 调用次数:批量传递数据而非频繁调用。
  • 使用局部引用缓存:避免重复查找类或方法 ID。
  • 直接访问缓冲区:如 GetPrimitiveArrayCriticalNewDirectByteBuffer
  • 避免跨线程调用:JNIEnv 是线程相关的,需正确处理线程绑定。

JNI 线程安全

问题:JNI 如何实现多线程安全?

  • 每个线程需通过 AttachCurrentThread 获取自己的 JNIEnv
  • 全局引用是线程安全的,但需注意同步问题。
  • 避免在本地代码中长时间持有对象引用,防止内存泄漏。

示例代码:

c 复制代码
JavaVM *jvm; // 全局变量
JNIEnv *env;
(*jvm)->AttachCurrentThread(jvm, (void **)&env, NULL);
// 调用 JNI 方法
(*jvm)->DetachCurrentThread(jvm);

JNI 常见问题

问题:JNI 调用时出现 UnsatisfiedLinkError 的可能原因?

  • 动态库未正确加载:路径错误或库名不匹配。
  • 方法签名不匹配:头文件中的函数名或参数与实现不一致。
  • 库依赖缺失:本地库依赖的其他库未正确部署。

问题:如何调试 JNI 代码?

  • 使用 printf 或日志输出调试信息。
  • 通过 gdblldb 调试本地代码。
  • 检查 adb logcat 输出的 Java 异常信息。

以上是常见的 JNI 面试题及答案,涵盖基础概念、开发流程、数据类型、异常处理、性能优化和线程安全等关键点。

相关推荐
chuan.bai2 小时前
Java RAG 实战(第 11 篇):RAG 知识工作台网页
java·开发语言·人工智能
0x534 小时前
网站通信(一)
java
Terra.K4 小时前
Java异常学习[特殊字符]
java·开发语言·学习
葡萄城技术团队6 小时前
InfluxDB 2\.x 深度解析:核心架构、Flux 函数与制造业落地指南(三)
java·开发语言·架构
Super 含6 小时前
Android 启动优化(五):线程、GC 与 IO 为什么会拖慢启动?
java·服务器·数据库
counting money6 小时前
Java IO流详解:从InputStream到文件操作实战
java·开发语言·python
程序员小八7777 小时前
上海百度B端java后端日常实习一面
java·开发语言
mldong8 小时前
零依赖的秘密:8 大 SPI 设计
java·架构
Diligently_10 小时前
Anolis 系统更新与密码设置&磁盘扩容
java·后端·spring