WhipsterCZ
WhipsterCZ

Reputation: 657

Kotlin Ktor Singleton doesn't work in development mode (auto-reload enabled)

I ran into a problem with broken singletons in Kotlin (Ktor Framework).

Problem is particullary Ktor Development mode. Everything is working correctly when it is disabled...

these two calls print out difference instances! I'm very surprised that didn't found any others mentions of this problem.. this is useless!

Is there anyone who has same problem?

# Application.kt

object Singleton {
    fun printInstanceId() {
        println("--> This is Singleton ${toString()}")
    }
}

fun main() {
    Singleton.printInstanceId() # <-- instance com.mallgroup.Singleton@27c170f0

    embeddedServer(Netty,port = 8080,module = Application::bootstrap).start(wait = true)
}

fun Application.bootstrap() {
    Singleton.printInstanceId() # <-- there is another instance!!! com.mallgroup.Singleton@18cebaa5

Terminal output

❯ sh gradlew run

> Configure project :
Environment: development , isDevelopment: true

> Task :compileKotlin
'compileJava' task (current target is 19) and 'compileKotlin' task (current target is 1.8) jvm target compatibility should be set to the same Java version.
By default will become an error since Gradle 8.0+! Read more: https://kotl.in/gradle/jvm/target-validation
Consider using JVM toolchain: https://kotl.in/gradle/jvm/toolchain


> Task :run
!!! This is Singleton com.mallgroup.Singleton@27c170f0
...
2023-01-04 15:28:53.352 [main] DEBUG ktor.application - Java Home: /Users/whipstercz/Library/Java/JavaVirtualMachines/openjdk-19.0.1/Contents
2023-01-04 15:28:53.354 [main] DEBUG ktor.application - Class Loader: jdk.internal.loader.ClassLoaders$AppClassLoader@5b37e0d2: [...]
2023-01-04 15:28:53.370 [main] DEBUG ktor.application - Watching /Users/whipstercz/Desktop/mal/ktor-autoreload/build/classes/kotlin/main/com/mallgroup/plugins for changes.
...
!!! This is Singleton com.mallgroup.Singleton@18cebaa5
2023-01-04 15:28:53.897 [main] INFO  ktor.application - Application started in 0.715 seconds.
2023-01-04 15:28:54.086 [main] INFO  ktor.application - Responding at http://0.0.0.0:8080

how is it possible that these are two different instances?

i have tried even different implementation of Singleton with same result..

class Singleton private constructor() {
    companion object {
        @Volatile
        private lateinit var instance: Singleton
        fun getInstance(): Singleton {
            synchronized(this) {
                if (!::instance.isInitialized) {
                    instance = Singleton()
                }
                return instance
            }
        }
    }

    fun printInstanceId() {
        println("This is Singleton ${toString()}")
    }
}

Upvotes: 0

Views: 573

Answers (1)

Aleksei Tirman
Aleksei Tirman

Reputation: 6999

Ktor's Auto Reloading loads a new version of a class via the class loader each time the class file is modified. Since object is implemented as a class with a static property assigned via a static initializer (executed when a class is being loaded), you get a new object instance after each reloading. KTOR-4843 is the related issue.

Upvotes: 3

Related Questions