Migrate to the new memory manager
This guide compares the new Kotlin/Native memory manager with the legacy one and describes how to migrate your projects.
The most noticeable change in the new memory manager is lifting restrictions on object sharing. You don't need to freeze objects to share them between threads, specifically:
Top-level properties can be accessed and modified by any thread without using
@SharedImmutable
.Objects passing through interop can be accessed and modified by any thread without freezing them.
Worker.executeAfter
no longer requires operations to be frozen.Worker.execute
no longer requires producers to return an isolated object subgraph.Reference cycles containing
AtomicReference
andFreezableAtomicReference
do not cause memory leaks.
Apart from easy object sharing, the new memory manager also brings other major changes:
Global properties are initialized lazily when the file they are defined in is accessed first. Previously global properties were initialized at the program startup. As a workaround, you can mark properties that must be initialized at the program start with the
@EagerInitialization
annotation. Before using, check its documentation.by lazy {}
properties support thread-safety modes and do not handle unbounded recursion.Exceptions that escape
operation
inWorker.executeAfter
are processed like in other runtime parts, by trying to execute a user-defined unhandled exception hook or terminating the program if the hook was not found or failed with an exception itself.Freezing is deprecated and always disabled.
Follow these guidelines to migrate your projects from the legacy memory manager:
Update Kotlin
The new Kotlin/Native memory manager has been enabled by default since Kotlin 1.7.20. Check the Kotlin version and update to the latest one if necessary.
Update dependencies
- kotlinx.coroutines
Update to version 1.6.0 or later. Do not use versions with the
native-mt
suffix.There are also some specifics with the new memory manager you should keep in mind:
Every common primitive (channels, flows, coroutines) works through the Worker boundaries, since freezing is not required.
Dispatchers.Default
is backed by a pool of Workers on Linux and Windows and by a global queue on Apple targets.Use
newSingleThreadContext
to create a coroutine dispatcher that is backed by a Worker.Use
newFixedThreadPoolContext
to create a coroutine dispatcher backed by a pool ofN
Workers.Dispatchers.Main
is backed by the main queue on Darwin and by a standalone Worker on other platforms.
- Ktor
Update to version 2.0 or later.
- Other dependencies
The majority of libraries should work without any changes, however, there might be exceptions.
Make sure that you update dependencies to the latest versions, and there is no difference between library versions for the legacy and the new memory manager.
Update your code
To support the new memory manager, remove usages of the affected API:
Old API | What to do | |
---|---|---|
You can remove all usages, though there are no warnings for using this API in the new memory manager. | ||
Use | ||
Remove all usages. | ||
Remove all usages. | ||
Remove all usages. | ||
Remove all usages. | ||
You can remove all usages. Since freezing is deprecated, the property always returns | ||
Remove all usages. | ||
Use | ||
Use any regular collection instead. | ||
Use | ||
Use |