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. 为何使用epoll+ eventfd?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 层对等。