摘要:JetBrains 推它很久了,说它能跨平台、能复用代码、运行效率高。但不少人听到“跨平台”三个字,第一反应还是:是不是又一个Flutter?是不是也要套个壳、跑个虚拟机?
Kotlin Multiplatform,是这两年开发圈里经常被提起的词。
JetBrains 推它很久了,说它能跨平台、能复用代码、运行效率高。但不少人听到“跨平台”三个字,第一反应还是:是不是又一个Flutter?是不是也要套个壳、跑个虚拟机?
其实不是。KMP 走的是另一条路。它不靠虚拟机,也不搞统一渲染,而是直接把 Kotlin 代码编译成目标平台的原生代码。
JetBrains 的说法是:KMP 编译器是前后端分离的,新增平台,只需要扩展后端就行。这句话听上去很轻巧,但真要理解清楚,还得拆开看。
KMP 的编译器确实分成了前后端两部分。前端负责把 Kotlin 源码转成 IR(中间表示),后端再把 IR 转成平台需要的二进制代码。这个设计的好处是,前端不用管平台差异,后端按平台来实现就行。
从设计上看,这没问题。但问题在于,后端真的不是个“插件”那么简单。
比如 Kotlin Native,它的后端是基于 LLVM 的。你得先把 Kotlin 的 IR 转成 LLVM IR,再用 Clang 编译,再做链接、优化,才能产出目标平台的可执行文件。所以, “只改后端”这事儿,理论上成立,工程上不轻松。
KMP 的其中一个卖点是性能。它不像 Flutter 或 React Native 需要解释器,而是直接编译到底层代码。拿 Kotlin Native 举例,最终生成的函数和 C/C++ 函数几乎没差别,调用开销低,运行效率也接近原生。
比如文中举的例子,一个加法函数 helloFun1,编译后就是一个标准的 C 函数,参数类型、返回值全都映射好了。这种方式,在性能上确实有优势。
但问题是,性能解决了,生态兼容还在。
Kotlin 原本就是跑在 JVM 上的。大部分 Kotlin 项目,都会用到 java 标准库或者 Android SDK。
这些库属于 java.* 或 android.* 包,在 KMP 里就只能在 JVM 或 Android 平台上用。这意味着,一旦你想把 Android 项目迁移到 iOS 或别的平台,改的地方可能不止一点点。
如果项目里没有提前把平台相关代码隔离好,就别指望“直接跨端”。
KMP 的定位不是“全栈跨平台”,而是“共享业务逻辑”。UI 层各平台自己处理,KMP 只管逻辑层。这种方式自由度高,开发者可以用原生的方式写 UI,不需要被框架限制住。
但灵活的代价,是生态得自己补。
JetBrains 自己维护了一些跨平台库,比如协程、序列化等。但大部分三方库还是只支持 JVM。像 AndroidX 的 Room 虽然在适配 KMP,但不是所有功能都能用。
这就导致一个问题:你写的“共享逻辑”,能不能真正跨平台,还得看用的库支不支持。
KMP 的 Runtime 也是自己做的,不依赖 JVM。Kotlin Native 有自己的内存分配器、线程系统、异常处理机制。GC 默认用的是 CMS,支持并发回收,性能还不错。
但它和 JVM 还是有不少区别。比如:不支持 synchronized,得用 atomicFu;不支持 SoftReference,只能用 WeakReference;数组对象的内存结构也和 JVM 不一样。
这些差异,可能在性能上没太大影响,但在代码迁移时就容易踩坑。
KMP 编译器确实做了很多事,从语法分析到中间表示,从代码优化到最终产物生成,流程完整、机制清晰。但有一点不能忽视:编译器帮你做不了平台隔离。
你得自己写一层封装,把平台相关代码隔离出来,然后才能复用中间那部分“逻辑代码”。所以说,KMP 能力强,但前提是你用得对。
KMP 确实不是传统意义上的跨平台框架。它不靠 UI 渲染引擎,也不跑虚拟机,而是编译器主导、源码级别的跨平台方案。你可以用它做到很高的性能复用,也可以因为平台差异被绊住脚步。
来源:老徐述往事