Native层实现

Android 消息机制的 Native 层实现,也就是 Java 层 Handler/Looper/MessageQueue 背后支撑的 JNI/C++代码 + Linux内核机制。我们就按照实际调用链,一步步从 Java 调到 Native,再到 Linux 的 epoll 和 eventfd,来系统性深入讲解 Native 层的底层实现

总览:Java 到 Native 的调用链

Java 层
 └── MessageQueue.next()
       ↓
    nativePollOnce(ptr, timeout)  ← JNI 调用
       ↓
    NativeMessageQueue::pollOnce() ← C++
       ↓
    Looper::pollOnce(timeout) ← C++
       ↓
    epoll_wait(epollFd, ...)

配套结构:

Java Looper/MessageQueue ←→ NativeMessageQueue ←→ Looper.cpp

1. MessageQueue.next()→ nativePollOnce()

Java 层 MessageQueue.java:

private native static long nativeInit();        // 创建 NativeMessageQueue
private native void nativeDestroy(long ptr);    // 销毁
private native void nativePollOnce(long ptr, int timeoutMillis); // 进入 epoll 阻塞
private native void nativeWake(long ptr);       // 唤醒 epoll_wait

这些 native 方法对应 C++ 实现:android_os_MessageQueue.cpp

2. nativePollOnce的 JNI 实现

文件:frameworks/base/core/jni/android_os_MessageQueue.cpp

static void android_os_MessageQueue_nativePollOnce(JNIEnv* env, jobject obj,
        jlong ptr, jint timeoutMillis) {
    NativeMessageQueue* nativeMessageQueue = reinterpret_cast<NativeMessageQueue*>(ptr);
    nativeMessageQueue->pollOnce(timeoutMillis);
}

3. NativeMessageQueue内部结构

class NativeMessageQueue : public LooperCallback {
public:
    NativeMessageQueue();
    ~NativeMessageQueue();

    void pollOnce(int timeoutMillis);   // 这里最终调用 Looper::pollOnce()
    void wake();                        // 写 eventfd 唤醒
private:
    sp<Looper> mLooper;                 // 真正处理 epoll 的 Looper 类
    int mWakeEventFd;                  // eventfd 文件描述符
    sp<EventHandler> mEventHandler;
};
  • 构造时创建 epoll_fd 和 eventfd:

    mWakeEventFd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
    mLooper = Looper::prepare(/* allowNonCallbacks */ true);
    mLooper->addFd(mWakeEventFd, …, ALOOPER_EVENT_INPUT, …, …);

4. 进入pollOnce→ 调用 epoll_wait

Looper.cpp 中:

int Looper::pollOnce(int timeoutMillis) {
    return pollInner(timeoutMillis);
}

int Looper::pollInner(int timeoutMillis) {
    int result = epoll_wait(mEpollFd, eventItems, capacity, timeoutMillis);
    ...
}
  • epollFd 是 Linux epoll 实例。

  • 当没有消息时,这里会阻塞,直到:

    • 新消息到来(通过 eventfd 唤醒)
    • 超时
    • 被外部 wake() 唤醒

5. 唤醒机制:nativeWake()

Java 调用:

MessageQueue.enqueueMessage(...) {
    ...
    nativeWake(mPtr);
}

JNI 层调用:

void NativeMessageQueue::wake() {
    uint64_t inc = 1;
    write(mWakeEventFd, &inc, sizeof(uint64_t));
}
  • 向 eventfd 写入数据 → 触发 epoll 读事件 → epoll_wait() 返回 → Java 继续处理消息。

6. 总结调用链

Java Handler.sendMessage()
 → MessageQueue.enqueueMessage()
   → nativeWake(mPtr)
     → write(eventfd)

Java MessageQueue.next()
 → nativePollOnce()
   → epoll_wait(epollFd) 阻塞
      ↑
   eventfd 可读 → epoll 返回

7. 为何使用epolleventfd?epoll 的作用

  • 类似 select 和 poll,用于监听多个 fd 的 I/O 可读/可写。
  • 比传统的 select 更高效,尤其在 fd 多的时候。

eventfd 的作用

  • 内核提供的轻量级信号量机制。
  • 一个 fd,只能做简单的计数器行为(+1, -1, 可读/写)。
  • 可以用于跨线程、线程唤醒。

在 MessageQueue 场景中:

  • epoll 用于阻塞等待事件
  • eventfd 用于通知消息队列中有新消息

8. 相关核心文件路径(AOSP)

模块 路径
MessageQueue.java frameworks/base/core/java/android/os/MessageQueue.java
Looper.cpp system/core/libutils/Looper.cpp
android_os_MessageQueue.cpp frameworks/base/core/jni/android_os_MessageQueue.cpp
NativeMessageQueue 上述 JNI 文件定义
eventfd/epoll Linux 内核 API

补充:Native 层 ALooper(NDK)

Android NDK 提供了 ALooper,它本质就是 Looper 的封装,也使用 epoll_wait 和 eventfd,可供 Native C/C++ 程序使用消息循环,与 Java 层对等。

当前网速较慢或者你使用的浏览器不支持博客特定功能,请尝试刷新或换用Chrome、Firefox等现代浏览器