Top-level property initialization: when does it happen?

I have two files:

initializer.kt:

private val shouldBeInitialized = Initializer.initialize()

public class Initializer {
    companion object {
        var initialized = false
        fun initialize() {
            initialized = true
        }
    }
}

main.kt:

fun main() {
    println("Something has been initialized: ${Initializer.initialized}")
}

This code builds cleanly for JVM, building it for native linux produces a warning.
When running it on JVM, it prints

Something has been initialized: false

When running it on native linux it crashes with an unhandled InvalidMutabilityException.

I have two questions:

  1. When is a top-level private property supposed to get initialized? As shown above, this has implications if the initialization has side effects.
  2. Clearly the semantics for this code is different between JVM and native platform. Should the semantics differ between the platforms in this case, and if not, which, if any, of the produced builds display a correct behavior?
1 Like

Kotlin doesn’t give you any guarantees when top level properties will be initialized. All you can say is that the initialization code will be called before you access a property, but you can’t necessarially tell when.

If you know which target platform you are on, you have a bit more information. I don’t know enough about native to help you there but on the JVM a top level property get’s initialized the when you call any top level function or property within the file. It’s a bit more complicated than that. It has to do with the JVM classloader and when that calls static initialization blocks (<clinit> function).
Maybe these links help to understand that:

I hope this helps with your first question (at least in regards to the JVM). The important part is that you can’t really put initialization code into top level properties and just expect them to be called in time. If you have some global initialization code that needs to be run for your library to work, it needs to be called explicitly by the consumer of your library.

2 Likes