May Day edition

Kotlin/Native v0.7 brings smoother interop, performance optimizations & more

Gabriela Motroc

© Shutterstock / Winter

One step closer to 1.0! Kotlin/Native 0.7 is here and it brings a lot of goodies including smoother interoperability with Objective-C and Swift, performance optimizations and more. Let’s have a look at the highlights.

Just in time for May Day! JetBrains has recently released Kotlin/Native v0.7, which promises to offer smoother interoperability with Objective-C and Swift, performance optimizations and plenty of bugfixes. Furthermore, both AppCode and CLion Kotlin/Native plugins have been updated to work with the latest release.

You’ll find the binaries here: macOSLinuxWindows.

Let’s have a look at the highlights.

Smoother interoperability with Objective-C and Swift

Let’s say you have this code on Kotlin side, compiled to the framework and later used from Swift:

fun isItTimeForKotlin(date: NSDate): String {
    val kotlin10Release = NSISO8601DateFormatter().dateFromString(
    return if (date.timeIntervalSinceDate(kotlin10Release) >= 0) "sure!" else "yes"

As JetBrains’ Nikolay Igotti explained in the blog post announcing the new version, calling Objective-C APIs like timeIntervalSinceDate() with an object coming from the Swift world could not have been done but v0.7 changed that. Here’s how you can call it:

let now = Date()
print(Common.isItTimeForKotlin(date: now))

Something else that wasn’t possible before is the ability to convert objects between Swift and Kotlin world transparently, i.e. which can now be done like this:

val string = "Kotlin" as NSString
val list = listOf(1, "Konan") as NSArray
val map = mapOf(1 to "one", 2 to "two") as NSDictionary

Now you can also convert Objective-C NSDictionary to Kotlin like this

val data = ("{ \"foo\": 1} " as NSString).dataUsingEncoding(NSUTF8StringEncoding)!!
val jsonObject = NSJSONSerialization.JSONObjectWithData(
    data, 0, null) as? Map<Any?, *> ?: throw Error("JSON parsing error")

and then use it as a regular Kotlin map. Easy, right?

Furthermore, one problem that appeared when creating UI is that even though one usually uses initializers override Kotlin’s constructors are not virtual. Here’s how to solve the problem:

class ViewController : UIViewController {
    @OverrideInit constructor(coder: NSCoder) : super(coder)
    @ObjCOutlet lateinit var button: UIButton
    @ObjCAction fun buttonPressed() {

As you can see, constructor accepting NSCoder is marked with @OverrideInit and is called virtually.

SEE ALSO: Kotlin Native serverless tutorial: Fun with Fibonacci

Memory model improvements

You might know this already but one of Kotlin/Native’s goals was to avoid shared data as much as possible. However, this doesn’t mean there aren’t cases in which one needs some shared immutable data. As Igotti explained in the blog post, one typical example is a configuration data, read from the file on startup and afterwards made available everywhere.

In order to make this happen, one would have to implement object freezing is implemented. Object might be:

  • in mutable state, owned by a single thread or worker,
  • immutable, and could be shared amongst multiple threads or worker, and could be freed once it’s no longer needed by consumers.
data class Config(val root: String, val version: Int)

fun init() {
    val config = Config("/path", 1).freeze()
    val workers = Array(10, { _ -> startWorker()})
    // Pass all workers a config.
    workers.forEach { it -> it.schedule(TransferMode.CHECKED, { config } ) {
        config -> println("got $config hash is ${config.hashCode()}")

The example showed above creates a frozen instance and can be passed to 10 workers (all share the same instance of configuration!). “Frozen objects has nice property of concurrent cycle-safe reference counter-based memory management, as during freezing process object graph is condensed to a DAG, and so could be collected basing on reference counter only. If one tries to mutate a frozen object, a runtime exception is thrown,” Igotti added. Therefore, by freezing them you’ll make sure the sharing of objects (across multiple threads or workers) is safer So freezing allows for safer sharing of objects across multiple threads or workers. Find out more about concurrency approaches in Kotlin/Native here.

Weak references is another requested feature which includes weak reference to Objective-C objects. This way you’ll know when you don’t need a certain object anymore and when it’s deallocated by the memory manager. You’ll be able to implement data structures like caches or break reference cycles when interoperating with the Objective-C world.

class Ref : NSObject() {
    var ref: WeakReference<NSObject> = WeakReference(this)

fun update(ref: Ref) = autoreleasepool {
    ref.ref = WeakReference(Ref())

fun test() {
    val x = Ref()
    println(x.ref.get())  // Gives reference to x.
    println(x.ref.get())  // Gives null.

Performance optimizations

Doing as many ahead of time optimizations as possible is one of Kotlin/Native’s goals. According to Igotti, a major enabler of such optimizations is building global call graph with the resolved polymorphism.

This can be done in the closed world compilation since all the pieces are known during the final code generation. Kotlin/Native will perform devirtualization analysis based on a call graph and cross-module type propagation, which allows for more optimizations, including escape analysis for arena-based memory allocator in the future.

Furthermore, box values for popular primitive types are now cached during compilation, which means they aren’t allocated in the runtime, thus saving memory management overhead.

Don’t forget to give it a try today and read the blog post announcing Kotlin/Native v0.7 here.

Gabriela Motroc
Gabriela Motroc was editor of and JAX Magazine. Before working at Software & Support Media Group, she studied International Communication Management at the Hague University of Applied Sciences.

Inline Feedbacks
View all comments