一、从一个问题开始在上一篇为什么 C 要改函数名一文讲透 gcc / g / C/C 混编本质我们讲了C 为什么要改函数名name manglingC/C 混编为什么会报错extern C 到底解决了什么 但其实这些问题背后还有一个更大的问题为什么 C/C 的问题都发生在“编译阶段” 而 Java / Android 的问题却常常发生在“运行时”二、核心答案先给结论所有技术的本质都在做一个选择把事情放在“编译期”做还是放在“运行时”做三、什么是编译期 vs 运行时✅ 编译期Compile Time程序还没运行编译器正在处理代码的阶段 比如gcc / g 编译类型检查函数符号确定模板展开✅ 运行时Runtime程序已经运行正在执行代码的阶段 比如JVM 执行字节码GC 回收内存JIT 动态优化反射 / AOP四、一个最关键的对比编译期提前做决定 运行时延迟做决定 用一句话总结提前 → 性能高 延迟 → 更灵活五、两大世界GCC vs JVM1️⃣ GCC / C 世界编译期为主源码 → 编译 → 机器码 → 直接执行 特点函数调用关系在编译期确定内存布局提前确定没有运行时系统几乎 举个例子int a 1 2; 编译后直接变成 3 ✔️ 这就是把工作提前做完2️⃣ JVM / Java 世界运行时为主源码 → 字节码 → JVM执行 特点方法调用运行时决定多态类加载动态完成有 GC / JIT 举个例子Animal a new Dog(); a.run(); JVM 在运行时决定调用 Dog.run()这就是把决策推迟到运行时六、为什么会有两种设计GCCC/C的设计目标 极致性能 可控性 所以尽量在编译期解决一切减少运行时开销接近硬件JVMJava的设计目标 跨平台 灵活性 安全性 所以推迟到运行时动态优化JIT支持反射 / 插件 / 热加载七、核心取舍一定要理解维度编译期C/C运行时Java性能⭐⭐⭐⭐⭐⭐⭐⭐⭐灵活性⭐⭐⭐⭐⭐⭐⭐跨平台❌✅控制力强较弱安全性低高八、一个非常重要的理解模型世界上所有语言都在这条轴上 编译期 ←──────────→ 运行时 举例C → 极端编译期 C → 偏编译期 Java → 偏运行时 Python → 极端运行时九、现代系统不再“二选一”现在的趋势是 编译期 运行时 混合AndroidART安装时AOT编译期 运行时JIT运行时☕ Java编译class 运行JIT优化 C模板编译期 虚函数运行时 ✔️ 本质把两种世界“融合”十、回到上一篇的问题❓ 为什么 C 会改函数名因为要在编译期区分函数支持重载❓ 为什么要 extern C让函数回到“简单模式”不改名 本质都是编译期行为十一、终极总结建议记住编译期提前做决定 → 性能 运行时延迟做决定 → 灵活 C/C尽量编译期解决 Java尽量运行时解决 现代系统两者结合这一篇我们建立了一个核心认知 编译期 vs 运行时 下一篇我们来看一个更具体的系统AOSPAndroid为什么是“编译期 运行时”的混合系统写在最后很多技术看起来完全不一样gcc / gJVM / ARTC / Java 但本质其实只有一件事 决策是在编译期做还是在运行时做一旦理解这个你会发现很多复杂问题都会变简单