从 C 对象模型 → JNI → HAL → Linux 内核接口——一条贯穿系统软件的完整认知链

补充知识点:

从 C 对象模型看 JNI:一行 (*env)->CallVoidMethod 背后的系统级真相

从函数表到 JNIEnv:彻底看懂 JNI 中的二级指针、结构体函数表与 -> 语法糖

一、所有系统接口的起点:C 语言"对象模型"

C 语言没有 class、没有 interface、没有 virtual。

但 Linux、Android、JVM、驱动、图形系统,全都需要:

  • 抽象接口
  • 模块解耦
  • 运行时切换实现
  • 多态能力

于是 C 世界形成了一套事实标准:

👉 struct 保存状态 + 函数指针保存行为

这就是所谓:

✅ C 语言对象模型

1. 最小对象模型

cpp 复制代码
struct Counter {
    int value;                         // 状态
    void (*inc)(struct Counter* self); // 行为
};
cpp 复制代码
void counter_inc(struct Counter* self) {
    self->value++;
}
cpp 复制代码
Counter c;
c.value = 0;
c.inc = counter_inc;
c.inc(&c);

你已经拥有了:

  • 对象(状态)
  • 方法(函数指针)
  • this(self)

👉 这在语义上已经是"面向对象"。

2. vtable(虚函数表)模型

系统里更常见的是这一层:

cpp 复制代码
struct CounterVTable {
    void (*inc)(struct Counter* self);
};

struct Counter {
    int value;
    const struct CounterVTable* vptr;
};

调用方式:

cpp 复制代码
counter->vptr->inc(counter);

👉 这已经和 C++ 虚函数机制几乎完全一致。

二、JNI:C 对象模型在虚拟机边界的体现

当你学 JNI 时,看到的是:

cpp 复制代码
(*env)->FindClass(env, "java/lang/String");

如果站在 C 对象模型视角,它非常直白:

  • env → 对象
  • JNINativeInterface_ → vtable
  • FindClass → 虚函数
  • env 作为第一个参数 → this

1. JNI 的真实结构

cpp 复制代码
struct JNINativeInterface_ {
    jclass (*FindClass)(JNIEnv*, const char*);
    jmethodID (*GetMethodID)(JNIEnv*, jclass, const char*, const char*);
    jobject (*CallObjectMethod)(JNIEnv*, jobject, jmethodID, ...);
    ...
};

typedef const struct JNINativeInterface_* JNIEnv;

调用:

(*env)->CallVoidMethod(env, obj, mid);

等价于:

env.vptr->CallVoidMethod(env, obj, mid);

👉 JNI 不是"库函数调用",

👉 JNI 是"通过接口表调用虚拟机能力"。

2. JNI 在整条链里的位置

cpp 复制代码
Java / Kotlin
     ↓
JNI (接口边界)
     ↓
C 对象模型(函数表)
     ↓
ART 虚拟机内部实现

JNI 本质是:

✅ 虚拟机向 native 世界暴露的一套"对象接口"。

三、HAL:系统服务与驱动之间的对象接口层

HAL(Hardware Abstraction Layer)是 Android 非常典型的系统层。

它的核心作用只有一句话:

👉 用统一接口,屏蔽不同硬件实现。

而它在代码层的实现,仍然是:

👉 struct + 函数指针

1. 典型 HAL 结构

cpp 复制代码
struct audio_hw_device {
    int (*init)(struct audio_hw_device* dev);
    int (*start)(struct audio_hw_device* dev);
    int (*stop)(struct audio_hw_device* dev);
};

不同厂商提供不同实现:

cpp 复制代码
struct audio_hw_device my_audio_dev = {
    .init = my_init,
    .start = my_start,
    .stop = my_stop
};

Framework 统一调用:

dev->start(dev);

👉 HAL 本质就是:

系统级接口对象 + 不同厂商的 vtable 实现。

2. HAL 在整条链的位置

cpp 复制代码
App / Framework
       ↓
   JNI / Binder
       ↓
   System Service
       ↓
        HAL   ←(统一接口层)
       ↓
   Vendor 实现
       ↓
    Driver

HAL 不是"模块",

HAL 是接口层设计思想的产物

四、Linux 内核:这套模型的源头

如果你进 Linux 内核,你会发现:

👉 几乎每一个子系统,都是"对象模型"。

1. 最经典的例子:file_operations

cpp 复制代码
struct file_operations {
    ssize_t (*read)(struct file*, char __user*, size_t, loff_t*);
    ssize_t (*write)(struct file*, const char __user*, size_t, loff_t*);
    int (*open)(struct inode*, struct file*);
};

ext4、procfs、设备文件,各自提供不同实现。

内核统一调用:

cpp 复制代码
file->f_op->read(file, buf, len, &pos);

👉 这就是内核级"多态"。

2. 再看几个你以后一定会遇到的

  • net_device_ops
  • usb_driver
  • tty_operations
  • inode_operations
  • platform_driver

它们结构完全一样:

👉 状态 struct + 操作表 ops

五、把四个层级放到一张统一认知图里

cpp 复制代码
【应用世界】
Java / Kotlin / Flutter
    ↓
【语言边界】
JNI / FFI
    ↓
【系统抽象层】
HAL / Service / Middleware
    ↓
【操作系统层】
Linux Kernel (VFS / Net / Driver)
    ↓
【硬件】

而贯穿全部层级的唯一共性是:

✅ struct + 函数指针

✅ 对象 + 方法表

✅ self / ctx 作为第一个参数

六、你以后如何"系统级读代码"

以后你再看到这种代码:

cpp 复制代码
dev->ops->write(dev, buf, len);
(*env)->CallVoidMethod(env, obj, mid);
engine->vptr->start(engine);

你要自动翻译成:

👉 对象

👉 接口表

👉 虚函数

👉 动态分发

👉 系统边界

这是一种系统工程视角,不是 API 视角。

七、一句话系统级总结

JNI 是虚拟机的对象接口

HAL 是系统的对象接口

Linux 内核是操作系统的对象接口

C 对象模型,是它们共同的语言。

八、检验你是否真正进入"系统层视角"

如果你现在看到:

struct xxx_ops { ... };

xxx->ops->do(xxx);

你脑子里出现的是:

👉 "对象模型 + vtable + 边界 + 可替换实现"

而不是:

👉 "这是什么 API"

那你已经不在"学技术",

你在进入系统工程世界

相关推荐
Evand J15 小时前
【MATLAB例程,附代码下载链接】基于累积概率的三维轨迹,概率计算与定位,由轨迹匹配和滤波带来高精度位置,带测试结果演示
开发语言·算法·matlab·csdn·轨迹匹配·候选轨迹·完整代码
warton8815 小时前
ubuntu24 安装 proxsql 实现数据库代理
linux·运维·mysql·ubuntu
Yuiiii__15 小时前
一次并不简单的 Spring 循环依赖排查
java·开发语言·数据库
野槐15 小时前
java基础-面向对象
java·开发语言
会跑的葫芦怪15 小时前
cursor 打开wsl Ubuntu项目
linux·运维·ubuntu
遇见~未来15 小时前
JavaScript构造函数与Class终极指南
开发语言·javascript·原型模式
foundbug99915 小时前
基于MATLAB的TDMP-LDPC译码器模型构建、仿真验证及定点实现
开发语言·matlab
用户4672445449915 小时前
linux的网络配置
linux
X***078815 小时前
从语言演进到工程实践全面解析C++在现代软件开发中的设计思想性能优势与长期生命力
java·开发语言
毕设源码-钟学长16 小时前
【开题答辩全过程】以 基于Python的车辆管理系统为例,包含答辩的问题和答案
开发语言·python