迁移到新内存管理器
Kotlin 1.9.20 已完全移除对旧版内存管理器的支持。请将您的项目迁移到当前的内存模型,该模型自 Kotlin 1.7.20 起已默认启用。
本指南将新的 Kotlin/Native 内存管理器与旧版进行了对比,并说明了如何迁移您的项目。
新内存管理器中最显著的变化是取消了对象共享限制。您无需冻结 (freeze) 对象即可在线程间共享,具体包括:
- 顶级属性可由任何线程访问和修改,无需使用
@SharedImmutable。 - 通过互操作 (interop) 传递的对象可由任何线程访问和修改,无需将其冻结。
Worker.executeAfter不再要求操作必须被冻结。Worker.execute不再要求生产者返回孤立的对象子图。- 包含
AtomicReference和FreezableAtomicReference的引用循环不会导致内存泄漏。
除了更轻松的对象共享,新内存管理器还带来了其他重大变化:
- 全局属性在首次访问其定义所在的文件时进行延迟初始化。以前,全局属性在程序启动时初始化。作为权宜之计,您可以使用
@EagerInitialization注解标记必须在程序启动时初始化的属性。在使用之前,请查阅其文档。 by lazy {}属性支持线程安全模式,且不处理无限递归。- 在
Worker.executeAfter中从operation逃逸的异常处理方式与运行时其他部分一致:尝试执行用户定义的未处理异常挂钩,如果未找到该挂钩或其本身抛出异常,则终止程序。 - 冻结 (Freezing) 已弃用并始终处于禁用状态。
请按照以下指南从旧版内存管理器迁移您的项目:
更新 Kotlin
新的 Kotlin/Native 内存管理器自 Kotlin 1.7.20 起已默认启用。请检查 Kotlin 版本,并在必要时更新到最新版本。
更新依赖项
更新到 1.6.0 或更高版本。不要使用带有 native-mt 后缀的版本。
关于新内存管理器,还有一些细节需要注意:
- 由于不再需要冻结,所有常用原语(通道、流、协程)都可以跨越工作线程 (Worker) 边界工作。
Dispatchers.Default在 Linux 和 Windows 上由工作线程池支持,在 Apple 目标平台上由全局队列支持。- 使用
newSingleThreadContext创建由工作线程支持的协程调度器。 - 使用
newFixedThreadPoolContext创建由N个工作线程组成的池支持的协程调度器。 Dispatchers.Main在 Darwin 上由主队列支持,在其他平台上由独立工作线程支持。
大多数库应该无需任何更改即可工作,但可能存在例外。
请确保将依赖项更新到最新版本,且旧版和新版内存管理器的库版本之间没有差异。
更新您的代码
要支持新内存管理器,请移除受影响 API 的用法:
| 旧版 API | 操作建议 |
|---|---|
@SharedImmutable | 您可以移除所有用法,尽管在新内存管理器中使用此 API 不会有警告。 |
FreezableAtomicReference 类 | 改为使用 AtomicReference。 |
FreezingException 类 | 移除所有用法。 |
InvalidMutabilityException 类 | 移除所有用法。 |
IncorrectDereferenceException 类 | 移除所有用法。 |
freeze() 函数 | 移除所有用法。 |
isFrozen 属性 | 您可以移除所有用法。由于冻结已弃用,该属性始终返回 false。 |
ensureNeverFrozen() 函数 | 移除所有用法。 |
atomicLazy() 函数 | 改为使用 lazy()。 |
MutableData 类 | 改为使用任何常规集合。 |
WorkerBoundReference<out T : Any> 类 | 直接使用 T。 |
DetachedObjectGraph<T> 类 | 直接使用 T。要通过 C 互操作传递值,请使用 StableRef 类。 |
