JNI的本质解析:Android Framework视角下的Java-Native衔接机制

JNI的本质解析:Android Framework视角下的Java-Native衔接机制

基于Android 14源代码分析


目录

  1. 概述
  2. JNI架构设计
  3. JNI注册机制:静态与动态的双轨制
  4. 核心数据结构:JNIEnv与JavaVM
  5. 完整调用链路剖析
  6. 实战案例:MessageQueue的JNI实现
  7. 性能优化与最佳实践
  8. 总结

1. 概述

1.1 什么是JNI?

JNI (Java Native Interface) 是Java平台提供的一套标准API,用于实现Java代码与本地C/C++代码之间的互操作。在Android系统中,JNI扮演着至关重要的角色,它是Java层Framework与底层Native代码的桥梁。

1.2 为什么Android需要JNI?

Android系统架构采用分层设计:

  • 应用层和Framework层:使用Java/Kotlin编写,提供高级API和业务逻辑
  • Native层:使用C/C++编写,提供底层系统调用、硬件访问和性能关键路径

JNI在其中承担的作用包括:

  1. 性能优化:将计算密集型任务交给Native代码执行
  2. 系统调用:访问Linux内核提供的系统调用
  3. 硬件抽象:通过HAL(Hardware Abstraction Layer)访问硬件设备
  4. 代码复用:复用已有的C/C++库

1.3 本文研究范围

本文基于Android 14 (AOSP) 源代码,深入分析以下内容:

  • JNI的注册机制
  • Java与Native之间的调用链路
  • 核心数据结构的实现
  • 实际案例分析

2. JNI架构设计

2.1 整体架构

复制代码
┌──────────────────────────────────────┐
│        Java Application Layer        │
│  (Java/Kotlin Code)                  │
└──────────────┬───────────────────────┘
               │ native method call
               ▼
┌──────────────────────────────────────┐
│          JNI Interface Layer         │
│  - JNIEnv (per-thread)               │
│  - JavaVM (per-process)              │
│  - Method Mapping                    │
└──────────────┬───────────────────────┘
               │
               ▼
┌──────────────────────────────────────┐
│       Native Implementation          │
│  (C/C++ Code in .so libraries)       │
└──────────────┬───────────────────────┘
               │
               ▼
┌──────────────────────────────────────┐
│      System Libraries / HAL          │
└──────────────────────────────────────┘

2.2 关键组件

在Android Framework中,JNI的核心组件位于以下位置:

组件 源码路径 作用
AndroidRuntime frameworks/base/core/jni/AndroidRuntime.cpp JNI运行时初始化和注册管理
JNI实现 frameworks/base/core/jni/*.cpp Framework各模块的JNI实现
JNIHelp libnativehelper/ JNI辅助工具库

3. JNI注册机制:静态与动态的双轨制

JNI方法注册是Java方法与Native函数建立映射关系的过程。Android支持两种注册方式。

3.1 静态注册(隐式注册)

3.1.1 原理

静态注册依赖命名规则,虚拟机在首次调用native方法时,根据固定的命名格式查找对应的Native函数。

命名格式:

复制代码
Java_<package_name>_<class_name>_<method_name>

例如:

  • Java方法:com.example.MyClass.nativeMethod()
  • 对应Native函数:Java_com_example_MyClass_nativeMethod()
3.1.2 优缺点

优点

  • 实现简单,无需手动注册代码
  • 适合小型项目和简单场景

缺点

  • 函数名冗长,可读性差
  • 首次调用时需要符号查找,性能较低
  • Android Framework中很少使用

3.2 动态注册(显式注册)

3.2.1 核心机制

Android Framework几乎全部采用动态注册方式。这种方式通过RegisterNatives()函数显式建立映射关系。

3.2.2 源码分析:AndroidRuntime的注册流程

第一步:定义注册函数表

frameworks/base/core/jni/AndroidRuntime.cpp中,定义了所有需要注册的模块:

cpp 复制代码
// frameworks/base/core/jni/AndroidRuntime.cpp:1472-1477
#ifdef NDEBUG
    #define REG_JNI(name)      { name }
    struct RegJNIRec {
        int (*mProc)(JNIEnv*);
    };
#else
    #define REG_JNI(name)      { name, #name }
    struct RegJNIRec {
        int (*mProc)(JNIEnv*);
        const char* mName;
    };
#endif

第二步:注册表数组

cpp 复制代码
// frameworks/base/core/jni/AndroidRuntime.cpp:1499-1527
static const RegJNIRec gRegJNI[] = {
    REG_JNI(register_com_android_internal_os_RuntimeInit),
    REG_JNI(register_com_android_internal_os_ZygoteInit_nativeZygoteInit),
    REG_JNI(register_android_os_SystemClock),
    REG_JNI(register_android_util_EventLog),
    REG_JNI(register_android_os_Binder),
    REG_JNI(register_android_os_Parcel),
    REG_JNI(register_android_os_MessageQueue),
    // ... 数百个注册项
};

第三步:统一注册入口

cpp 复制代码
// frameworks/base/core/jni/AndroidRuntime.cpp:1669-1698
/*static*/ int AndroidRuntime::startReg(JNIEnv* env)
{
    ATRACE_NAME("RegisterAndroidNatives");

    /*
     * 设置线程创建钩子,使所有新线程自动附加到JavaVM
     */
    androidSetCreateThreadFunc((android_create_thread_fn) javaCreateThreadEtc);

    ALOGV("--- registering native functions ---\n");

    /*
     * 使用PushLocalFrame管理本地引用
     * 注册过程会创建大量本地引用(如FindClass),需要及时释放
     */
    env->PushLocalFrame(200);

    // 批量注册所有JNI方法
    if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) {
        env->PopLocalFrame(NULL);
        return -1;
    }

    env->PopLocalFrame(NULL);
    return 0;
}

第四步:调用时机

在AndroidRuntime启动虚拟机时调用:

cpp 复制代码
// frameworks/base/core/jni/AndroidRuntime.cpp:1236-1251
/* start the virtual machine */
JniInvocation jni_invocation;
jni_invocation.Init(NULL);
JNIEnv* env;
if (startVm(&mJavaVM, &env, zygote, primary_zygote) != 0) {
    return;
}
onVmCreated(env);

/*
 * Register android functions.
 */
if (startReg(env) < 0) {
    ALOGE("Unable to register all android natives\n");
    return;
}

3.3 具体模块的注册实现

MessageQueue为例,展示完整的注册过程:

3.3.1 定义JNI方法表
cpp 复制代码
// frameworks/base/core/jni/android_os_MessageQueue.cpp:246-255
static const JNINativeMethod gMessageQueueMethods[] = {
    /* name, signature, funcPtr */
    { "nativeInit", "()J", (void*)android_os_MessageQueue_nativeInit },
    { "nativeDestroy", "(J)V", (void*)android_os_MessageQueue_nativeDestroy },
    { "nativePollOnce", "(JI)V", (void*)android_os_MessageQueue_nativePollOnce },
    { "nativeWake", "(J)V", (void*)android_os_MessageQueue_nativeWake },
    { "nativeIsPolling", "(J)Z", (void*)android_os_MessageQueue_nativeIsPolling },
    { "nativeSetFileDescriptorEvents", "(JII)V",
            (void*)android_os_MessageQueue_nativeSetFileDescriptorEvents },
};

方法表结构说明

  • name:Java层native方法名
  • signature:JNI方法签名(参数和返回值类型)
  • funcPtr:对应的C++函数指针

JNI签名规则

Java类型 JNI签名
void V
boolean Z
int I
long J
String Ljava/lang/String;
int[] [I
3.3.2 注册函数实现
cpp 复制代码
// frameworks/base/core/jni/android_os_MessageQueue.cpp:257-267
int register_android_os_MessageQueue(JNIEnv* env) {
    // 注册native方法
    int res = RegisterMethodsOrDie(env, "android/os/MessageQueue",
                                   gMessageQueueMethods,
                                   NELEM(gMessageQueueMethods));

    // 缓存Java类的字段和方法ID(性能优化)
    jclass clazz = FindClassOrDie(env, "android/os/MessageQueue");
    gMessageQueueClassInfo.mPtr = GetFieldIDOrDie(env, clazz, "mPtr", "J");
    gMessageQueueClassInfo.dispatchEvents = GetMethodIDOrDie(env, clazz,
            "dispatchEvents", "(II)I");

    return res;
}

关键点分析

  1. RegisterMethodsOrDie:批量注册方法,失败则终止进程
  2. 缓存字段和方法ID:避免运行时频繁查找,提升性能
  3. 全局结构体:将ID存储在静态结构体中
cpp 复制代码
// frameworks/base/core/jni/android_os_MessageQueue.cpp:30-33
static struct {
    jfieldID mPtr;   // native object attached to the DVM MessageQueue
    jmethodID dispatchEvents;
} gMessageQueueClassInfo;

4. 核心数据结构:JNIEnv与JavaVM

4.1 JavaVM:进程级虚拟机实例

4.1.1 定义与作用

JavaVM代表整个Java虚拟机实例,每个进程只有一个JavaVM对象。

主要功能

  • 创建和销毁虚拟机
  • 附加/分离线程
  • 获取JNIEnv指针
4.1.2 源码中的使用
cpp 复制代码
// frameworks/base/core/jni/AndroidRuntime.cpp:299
/*static*/ JavaVM* AndroidRuntime::mJavaVM = NULL;

// 获取JavaVM实例
/*static*/ JavaVM* AndroidRuntime::getJavaVM() {
    return AndroidRuntime::mJavaVM;
}

// frameworks/base/core/jni/AndroidRuntime.cpp:1329-1331
extern "C" JavaVM* AndroidRuntimeGetJavaVM() {
    return AndroidRuntime::getJavaVM();
}
4.1.3 线程附加机制

Native线程需要附加到JavaVM才能调用Java代码:

cpp 复制代码
// frameworks/base/core/jni/AndroidRuntime.cpp:1338-1347
/*static*/ JNIEnv* AndroidRuntime::getJNIEnv()
{
    JNIEnv* env;
    JavaVM* vm = AndroidRuntime::getJavaVM();
    assert(vm != NULL);

    if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK)
        return NULL;  // 线程未附加
    return env;
}

4.2 JNIEnv:线程级接口指针

4.2.1 本质

JNIEnv是一个指向函数表的指针,每个线程都有独立的JNIEnv实例。

为什么是线程独立的?

  • 避免多线程竞争
  • 支持线程本地异常处理
  • 简化JNI实现
4.2.2 常用API分类

1. 类和对象操作

cpp 复制代码
jclass FindClass(const char* name);
jobject NewObject(jclass clazz, jmethodID methodID, ...);
jclass GetObjectClass(jobject obj);

2. 字段访问

cpp 复制代码
jfieldID GetFieldID(jclass clazz, const char* name, const char* sig);
jint GetIntField(jobject obj, jfieldID fieldID);
void SetIntField(jobject obj, jfieldID fieldID, jint value);

3. 方法调用

cpp 复制代码
jmethodID GetMethodID(jclass clazz, const char* name, const char* sig);
void CallVoidMethod(jobject obj, jmethodID methodID, ...);
jint CallIntMethod(jobject obj, jmethodID methodID, ...);

4. 异常处理

cpp 复制代码
jboolean ExceptionCheck();
jthrowable ExceptionOccurred();
void ExceptionClear();
void Throw(jthrowable obj);

5. 引用管理

cpp 复制代码
jobject NewLocalRef(jobject ref);
void DeleteLocalRef(jobject localRef);
jobject NewGlobalRef(jobject obj);
void DeleteGlobalRef(jobject globalRef);

5. 完整调用链路剖析

5.1 Java调用Native:从上到下

流程图
复制代码
Java Application
     │
     │ 1. 调用native方法
     ▼
MessageQueue.nativePollOnce(ptr, timeout)
     │
     │ 2. ART查找native函数地址(已注册)
     ▼
android_os_MessageQueue_nativePollOnce()
     │
     │ 3. 解析参数
     ▼
NativeMessageQueue::pollOnce(env, obj, timeoutMillis)
     │
     │ 4. 调用Native逻辑
     ▼
Looper::pollOnce(timeoutMillis)
     │
     │ 5. 系统调用
     ▼
epoll_wait() [Linux kernel]
详细步骤

Step 1: Java层声明native方法

java 复制代码
// frameworks/base/core/java/android/os/MessageQueue.java:69-73
private long mPtr; // used by native code

private native static long nativeInit();
private native static void nativeDestroy(long ptr);
private native void nativePollOnce(long ptr, int timeoutMillis);
private native static void nativeWake(long ptr);

Step 2: JNI层实现

cpp 复制代码
// frameworks/base/core/jni/android_os_MessageQueue.cpp:222-226
static void android_os_MessageQueue_nativePollOnce(JNIEnv* env, jobject obj,
        jlong ptr, jint timeoutMillis) {
    NativeMessageQueue* nativeMessageQueue = reinterpret_cast<NativeMessageQueue*>(ptr);
    nativeMessageQueue->pollOnce(env, obj, timeoutMillis);
}

关键点

  • jlong ptr:从Java层传递的Native对象指针(转换为long)
  • reinterpret_cast:将long指针还原为C++对象指针

Step 3: Native对象实现

cpp 复制代码
// frameworks/base/core/jni/android_os_MessageQueue.cpp:122-134
void NativeMessageQueue::pollOnce(JNIEnv* env, jobject pollObj, int timeoutMillis) {
    mPollEnv = env;
    mPollObj = pollObj;
    mLooper->pollOnce(timeoutMillis);  // 调用底层Looper
    mPollObj = NULL;
    mPollEnv = NULL;

    // 处理异常
    if (mExceptionObj) {
        env->Throw(mExceptionObj);
        env->DeleteLocalRef(mExceptionObj);
        mExceptionObj = NULL;
    }
}

5.2 Native回调Java:从下到上

场景示例

当Native层检测到文件描述符事件时,需要回调Java层的dispatchEvents方法。

实现代码
cpp 复制代码
// frameworks/base/core/jni/android_os_MessageQueue.cpp:157-178
int NativeMessageQueue::handleEvent(int fd, int looperEvents, void* data) {
    int events = 0;
    if (looperEvents & Looper::EVENT_INPUT) {
        events |= CALLBACK_EVENT_INPUT;
    }
    if (looperEvents & Looper::EVENT_OUTPUT) {
        events |= CALLBACK_EVENT_OUTPUT;
    }
    if (looperEvents & (Looper::EVENT_ERROR | Looper::EVENT_HANGUP | Looper::EVENT_INVALID)) {
        events |= CALLBACK_EVENT_ERROR;
    }

    int oldWatchedEvents = reinterpret_cast<intptr_t>(data);

    // 通过JNIEnv调用Java方法
    int newWatchedEvents = mPollEnv->CallIntMethod(mPollObj,
            gMessageQueueClassInfo.dispatchEvents, fd, events);

    if (!newWatchedEvents) {
        return 0; // unregister the fd
    }
    if (newWatchedEvents != oldWatchedEvents) {
        setFileDescriptorEvents(fd, newWatchedEvents);
    }
    return 1;
}

关键技术点

  1. 保存JNIEnv :在pollOnce时保存,回调时使用
  2. 使用缓存的methodIDgMessageQueueClassInfo.dispatchEvents
  3. 类型转换:JNI类型与Java类型的映射

6. 实战案例:MessageQueue的JNI实现

6.1 架构设计

MessageQueue是Android消息机制的核心组件,其JNI设计是典型的Java-Native协作模式。

设计思想
复制代码
Java层MessageQueue
  ├─ 提供高级API(enqueueMessage, next等)
  ├─ 持有Native对象指针(mPtr)
  └─ 委托Native层执行阻塞操作

Native层NativeMessageQueue
  ├─ 持有Looper对象
  ├─ 封装epoll机制
  └─ 处理文件描述符事件

6.2 对象生命周期管理

创建流程

Java层

java 复制代码
// frameworks/base/core/java/android/os/MessageQueue.java:79
MessageQueue(boolean quitAllowed) {
    mQuitAllowed = quitAllowed;
    mPtr = nativeInit();  // 创建Native对象
}

Native层

cpp 复制代码
// frameworks/base/core/jni/android_os_MessageQueue.cpp:206-215
static jlong android_os_MessageQueue_nativeInit(JNIEnv* env, jclass clazz) {
    NativeMessageQueue* nativeMessageQueue = new NativeMessageQueue();
    if (!nativeMessageQueue) {
        jniThrowRuntimeException(env, "Unable to allocate native queue");
        return 0;
    }

    nativeMessageQueue->incStrong(env);  // 增加引用计数
    return reinterpret_cast<jlong>(nativeMessageQueue);  // 返回指针作为long
}

NativeMessageQueue构造函数

cpp 复制代码
// frameworks/base/core/jni/android_os_MessageQueue.cpp:93-100
NativeMessageQueue::NativeMessageQueue() :
        mPollEnv(NULL), mPollObj(NULL), mExceptionObj(NULL) {
    mLooper = Looper::getForThread();
    if (mLooper == NULL) {
        mLooper = new Looper(false);
        Looper::setForThread(mLooper);
    }
}
销毁流程

Java层

java 复制代码
// frameworks/base/core/java/android/os/MessageQueue.java:95
private void dispose() {
    if (mPtr != 0) {
        nativeDestroy(mPtr);
        mPtr = 0;
    }
}

Native层

cpp 复制代码
// frameworks/base/core/jni/android_os_MessageQueue.cpp:217-220
static void android_os_MessageQueue_nativeDestroy(JNIEnv* env, jclass clazz, jlong ptr) {
    NativeMessageQueue* nativeMessageQueue = reinterpret_cast<NativeMessageQueue*>(ptr);
    nativeMessageQueue->decStrong(env);  // 减少引用计数,可能触发析构
}

6.3 线程安全设计

环境保存机制
cpp 复制代码
// frameworks/base/core/jni/android_os_MessageQueue.cpp:69-73
private:
    JNIEnv* mPollEnv;      // 当前轮询的线程环境
    jobject mPollObj;      // Java层MessageQueue对象
    jthrowable mExceptionObj;  // 待抛出的异常

为什么需要保存?

  • pollOnce可能触发回调,回调需要访问Java对象
  • 异常需要在正确的线程环境中抛出

6.4 异常处理机制

cpp 复制代码
// frameworks/base/core/jni/android_os_MessageQueue.cpp:82-91
bool MessageQueue::raiseAndClearException(JNIEnv* env, const char* msg) {
    if (env->ExceptionCheck()) {
        jthrowable exceptionObj = env->ExceptionOccurred();
        env->ExceptionClear();
        raiseException(env, msg, exceptionObj);
        env->DeleteLocalRef(exceptionObj);
        return true;
    }
    return false;
}
cpp 复制代码
// frameworks/base/core/jni/android_os_MessageQueue.cpp:105-120
void NativeMessageQueue::raiseException(JNIEnv* env, const char* msg, jthrowable exceptionObj) {
    if (exceptionObj) {
        if (mPollEnv == env) {
            // 在轮询线程中,保存异常稍后抛出
            if (mExceptionObj) {
                env->DeleteLocalRef(mExceptionObj);
            }
            mExceptionObj = jthrowable(env->NewLocalRef(exceptionObj));
            ALOGE("Exception in MessageQueue callback: %s", msg);
            jniLogException(env, ANDROID_LOG_ERROR, LOG_TAG, exceptionObj);
        } else {
            // 不在轮询线程,直接致命错误
            ALOGE("Exception: %s", msg);
            jniLogException(env, ANDROID_LOG_ERROR, LOG_TAG, exceptionObj);
            LOG_ALWAYS_FATAL("raiseException() was called when not in a callback, exiting.");
        }
    }
}

7. 性能优化与最佳实践

7.1 缓存字段和方法ID

原理

字段和方法ID查找是昂贵的操作,应该在注册时缓存。

实践
cpp 复制代码
// frameworks/base/core/jni/android_os_MessageQueue.cpp:30-33
static struct {
    jfieldID mPtr;
    jmethodID dispatchEvents;
} gMessageQueueClassInfo;

// 注册时初始化
int register_android_os_MessageQueue(JNIEnv* env) {
    // ...
    jclass clazz = FindClassOrDie(env, "android/os/MessageQueue");
    gMessageQueueClassInfo.mPtr = GetFieldIDOrDie(env, clazz, "mPtr", "J");
    gMessageQueueClassInfo.dispatchEvents = GetMethodIDOrDie(env, clazz,
            "dispatchEvents", "(II)I");
    return res;
}

性能对比

  • 每次调用查找:FindClass + GetMethodID ≈ 1000ns
  • 使用缓存:直接访问 ≈ 10ns

7.2 本地引用管理

问题

JNI调用创建的本地引用(Local Reference)需要手动释放,否则会导致内存泄漏。

解决方案

方案1:手动释放

cpp 复制代码
jstring str = env->NewStringUTF("test");
// 使用str...
env->DeleteLocalRef(str);

方案2:使用PushLocalFrame/PopLocalFrame

cpp 复制代码
env->PushLocalFrame(100);  // 预分配100个引用槽位
// 创建大量本地引用...
env->PopLocalFrame(NULL);  // 批量释放

AndroidRuntime中的实践

cpp 复制代码
// frameworks/base/core/jni/AndroidRuntime.cpp:1687-1693
env->PushLocalFrame(200);

if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) {
    env->PopLocalFrame(NULL);
    return -1;
}
env->PopLocalFrame(NULL);

7.3 全局引用的正确使用

场景

Native层需要长期持有Java对象时,必须使用全局引用。

示例
cpp 复制代码
class MyNativeClass {
private:
    jobject mJavaCallback;  // 错误:应该用全局引用

public:
    void setCallback(JNIEnv* env, jobject callback) {
        // 正确做法
        if (mJavaCallback) {
            env->DeleteGlobalRef(mJavaCallback);
        }
        mJavaCallback = env->NewGlobalRef(callback);
    }

    ~MyNativeClass() {
        // 必须在析构时释放
        if (mJavaCallback) {
            JNIEnv* env = AndroidRuntime::getJNIEnv();
            env->DeleteGlobalRef(mJavaCallback);
        }
    }
};

7.4 减少JNI边界跨越

原则

JNI调用有固定开销(约20-200ns),应该批量处理数据。

反例
cpp 复制代码
// 每次传递一个元素(性能差)
for (int i = 0; i < 10000; i++) {
    env->CallVoidMethod(obj, processMethod, data[i]);
}
正例
cpp 复制代码
// 批量传递数组
jintArray arr = env->NewIntArray(10000);
env->SetIntArrayRegion(arr, 0, 10000, data);
env->CallVoidMethod(obj, processBatchMethod, arr);
env->DeleteLocalRef(arr);

7.5 异常检查

规则

调用可能抛出异常的JNI函数后,必须检查异常。

实践
cpp 复制代码
jclass clazz = env->FindClass("com/example/MyClass");
if (env->ExceptionCheck()) {
    env->ExceptionClear();
    // 处理异常...
    return -1;
}

AndroidRuntime的封装

cpp 复制代码
// 使用OrDie系列函数,异常时直接终止进程
jclass clazz = FindClassOrDie(env, "android/os/MessageQueue");
jfieldID field = GetFieldIDOrDie(env, clazz, "mPtr", "J");

8. 总结

8.1 核心要点回顾

  1. 双轨注册机制

    • 静态注册:命名规则,自动查找
    • 动态注册:显式映射,性能更优(Android Framework主流)
  2. 核心数据结构

    • JavaVM:进程级虚拟机实例
    • JNIEnv:线程级接口指针
  3. 调用链路

    • Java → Native:native方法声明 → JNI层转换 → Native实现
    • Native → Java:JNIEnv::Call*Method → 使用缓存的methodID
  4. 生命周期管理

    • Native对象通过long指针传递给Java层
    • 使用强引用计数管理对象生命周期
    • 全局引用用于长期持有Java对象
  5. 性能优化

    • 缓存字段和方法ID
    • 正确管理本地/全局引用
    • 减少JNI边界跨越
    • 批量处理数据

8.2 Android Framework的JNI设计哲学

通过对Android 14源码的深入分析,我们可以总结出Framework层JNI设计的核心原则:

  1. 职责分离:Java层处理业务逻辑,Native层处理系统调用和性能关键路径
  2. 统一管理:通过AndroidRuntime集中管理所有JNI注册
  3. 性能优先:大量使用缓存、批量处理、引用计数等优化手段
  4. 健壮性:完善的异常处理、引用管理、线程安全机制

8.3 实践建议

对于Android开发者和系统工程师:

  1. 遵循Framework的注册模式:使用动态注册,集中管理
  2. 重视性能优化:缓存ID、批量处理、减少跨越
  3. 严格的资源管理:正确使用本地/全局引用,避免内存泄漏
  4. 防御性编程:完善异常检查,确保线程安全

附录:源码索引

主题 源码路径 关键行号
AndroidRuntime初始化 frameworks/base/core/jni/AndroidRuntime.cpp 1236-1251
JNI注册表 frameworks/base/core/jni/AndroidRuntime.cpp 1499-1650
startReg函数 frameworks/base/core/jni/AndroidRuntime.cpp 1669-1698
MessageQueue JNI实现 frameworks/base/core/jni/android_os_MessageQueue.cpp 全文
MessageQueue Java声明 frameworks/base/core/java/android/os/MessageQueue.java 69-75
JNI方法注册 frameworks/base/core/jni/android_os_MessageQueue.cpp 246-267
Native回调Java frameworks/base/core/jni/android_os_MessageQueue.cpp 157-178

相关推荐
indexsunny2 小时前
互联网大厂Java求职面试实录:Spring Boot微服务在电商场景中的应用及技术深度解析
java·数据库·spring boot·缓存·微服务·面试·电商
夏幻灵2 小时前
Java中的this关键字解析与应用
java·开发语言·python
猿小羽2 小时前
Spring AI + MCP 实战:构建下一代智能 Agent 应用
java·spring boot·llm·ai agent·spring ai·mcp·model context protocol
baivfhpwxf20232 小时前
C# Task.Run 和 Task.Factory.StartNew 的区别
开发语言·c#
难得的我们2 小时前
C++中的状态模式
开发语言·c++·算法
浪客川2 小时前
1972 GODOT 入门案例
android·java·godot
eWidget2 小时前
Shell循环进阶:break/continue,循环嵌套与优化技巧
运维·开发语言·ffmpeg·运维开发
爱喝水的鱼丶2 小时前
SAP-ABAP:从SAP中暴露REST API:完整实操SICF接口开发指南
运维·开发语言·api·sap·abap·rest·接口开发
乂爻yiyao2 小时前
HotSpot 内存区域详解
java·jvm