Reputation: 657
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
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