Kotlin/Native v0.9 is here!

Posted on by

Summer may be almost over, but our Kotlin/Native team has been breaking a sweat to give you the Kotlin/Native v0.9 release… and here it is! Don’t be fooled by the numbering – this is a major (and breaking) release of our compiler toolchain, Gradle plugin, and IDE plugin.

Following are the most important changes in this release:

Migration to Kotlin 1.3-M2 (compiler and standard library)

Support for unsigned types in Kotlin stdlib

Support for unsigned types in C/Objective-C/Swift interop layer

Support for a stable version of kotlin.coroutines

Reworked concurrency primitives

The kotlin.native package

Kotlin 1.3-M2 support

To support the upcoming release of Kotlin 1.3, Kotlin/Native v0.9 is already based on the milestone Kotlin 1.3-M2 compiler and standard library. This means all the goodies of the new language version, such as inline classes, unsigned types, and common random number generator API, are available on all native targets.

Unsigned types support

Kotlin as a programming language with version 1.3 has received support for unsigned types in both language and the standard library, across all backends, i.e. JVM, Native, and JS. For example, code like this

fun main(args: Array<String>) { println(maxOf(1u, UInt.MAX_VALUE)) }

works correctly on all Kotlin flavors and prints 4294967295 . Many popular operations in the standard library are extended to support unsigned operands, and can be used out of the box.

Unsigned types and interop

We not only support unsigned types in the language itself, but also map Kotlin unsigned types to appropriate C and Objective-C/Swift types, meaning interoperability layer is even better in terms of matching the Kotlin and platform worlds. For example, let’s take a look at the following networking code, which reads data from the socket to Kotlin’s ByteArray :

buffer.usePinned { pinned -> while (true) { val length = recv(commFd, pinned.addressOf(0), buffer.size.convert(), 0).toInt() .ensureUnixCallResult("read") { it >= 0 } if (length == 0) break send(commFd, pinned.addressOf(0), length.convert(), 0) .ensureUnixCallResult("send") { it >= 0 } } }

Note that now we explicitly see places where potentially unsafe conversions between signed and unsigned values may happen (marked with the convert() intrinsic), and POSIX API

ssize_t recv(int socket, void *buffer, size_t length, int flags);

is correctly translated to a Kotlin signature as follows:

typealias ssize_t = Long typealias size_t = ULong ... fun recv(arg0: Int, arg1: CValuesRef<*>?, arg2: size_t, arg3: Int): ssize_t

Support stable coroutines

As coroutines are no longer in the experimental state and are officially production-ready in Kotlin 1.3, we now support new coroutines APIs in Kotlin/Native v0.9. Experimental coroutines from kotlin.coroutines.experimental are no longer supported neither in the compiler nor at the runtime.

Reworked concurrency primitives

Kotlin/Native v0.8 introduced freezing of singleton objects, which allows creating a reliable shared global state across multiple concurrent executors. With v0.9, we’ve seriously reworked all the concurrency primitives and moved them to the new kotlin.native.concurrent package. Important changes include:

AtomicInt , AtomicLong , AtomicNativePtr and AtomicReference classes API were seriously reworked

, , and classes API were seriously reworked lazy delegate was improved to work properly with the frozen objects

a new DetachedObjectGraph class encapsulating detached object subgraph concept is provided

For example, the following code:

dispatch_async_f(asyncQueue, DetachedObjectGraph { Data(clock_gettime_nsec_np(CLOCK_REALTIME)) }.asCPointer(), staticCFunction { it -> initRuntimeIfNeeded() val data = DetachedObjectGraph<Data>(it).attach() println("in async: $data") })

can pass ownership of the mutable object Data to another async queue on macOS.

Another important aspect of concurrency support was that previously, top-level variables were thread-local, and now they could only be accessed from the main thread of the application, while all other access attempts led to runtime exceptions. To control this behavior, we’ve introduced new annotations, @ThreadLocal and @SharedImmutable , so that top-level variables marked with such an annotation are thread-local or frozen after initialization, respectively.

kotlin.native package

To ensure a better structured standard library and support writing multi-platform code, all code was moved from the konan package to kotlin.native , and interfaces were seriously reworked and cleaned up to better align with the multi-platform Kotlin paradigm. Some native-specific operations having counterparts in the common stdlib were made internal or private, to promote use of portable standard operations.

Getting the bits

Check out the GitHub release page for more details or download binaries for macOS, Linux, or Windows. A Linux Snap package is also available.