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 函数后,使用 ExceptionCheck 或 ExceptionOccurred 检查是否有异常。
  • 抛出异常:通过 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。
  • 直接访问缓冲区:如 GetPrimitiveArrayCritical 或 NewDirectByteBuffer。
  • 避免跨线程调用: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 或日志输出调试信息。
  • 通过 gdb 或 lldb 调试本地代码。
  • 检查 adb logcat 输出的 Java 异常信息。

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

相关推荐
Pniubi7 小时前
HashMap的扩容和树化边界
java·开发语言
Mikko77 小时前
用 Java 复刻了高中时在塞班上玩的「熔岩矿车」:纯 Swing、零依赖、没有一张图片,一个 jar 双击就能玩
java·游戏开发·swing
知了学历孙老师7 小时前
小自考的校考和统考,出题方和难度差在哪
java·大数据·前端
Java爱好狂.8 小时前
Java初学者如何一周速通SpringBoot!
java·spring boot·后端·spring·高并发·架构师·java面试
秋饼9 小时前
LLM API密钥动态轮换实战:Spring Vault + Spring AI + 多Provider路由
java·ai·技术分享·后端开发
福兮说10 小时前
JSON 格式正确,数据就可靠吗?我用一份自编配置检查类型与空值
java·前端·json
紧跟先前的步伐11 小时前
Go AI Agent 实战 03|Token、上下文窗口与模型调用成本
java·人工智能·golang
const_qiu12 小时前
第四章 00:开篇 —— 从「会聊天」到「记得住、会干活、能协作」
java·开发语言·人工智能·python
Wang's Blog12 小时前
Java 项目实战: 交友项目 - 个人资料管理的更新接口实现与坑
java·开发语言·交友
Promising_GEO12 小时前
GEE实战02期:从卫星波段开始:利用 Sentinel-2 自己计算 NDVI
java·sentinel·遥感·空间分析