Namek Dev
a developer's log
NamekDev

Kotlin vs Object Pooling - nullify lateinit variable

March 12, 2017
Kotlin vs Object Pooling - nullify lateinit variable

Nullable type is a good thing. Until you prevent memory allocation to fight Garbage Collection pauses. I want to nullify lateinit variable - I can’t. Or can I?

Nullify lateinit

Sometimes you have to nullify things. There are multiple reasons, most of them is the external code. To reduce amount of work that has to be done by Garbage Collector (even if JVM is doesn’t memleak as ActionScript)

class AIComponent : PooledComponent {
    lateinit var steerable: SteerableEntity
    
    override fun reset() {
        steerable = null // ERROR! I CAN'T DO THAT!
    }
}

Easy “solution” is not to use lateinit at all by making it nullable:

class AIComponent : PooledComponent {
    var steerable: SteerableEntity? = null
    
    override fun reset() {
        steerable = null
    }
}

but accessing nullable variable is not convenient. Instead of just using steerable  I would have to write steerable!! .

Use Reflection!

No, well, no. It’s too slow. Inspection and stuff. Especially on Android.

There’s a more performant way - cache your reflection as bytecode instructions. And there is a library for it - ReflectASM. Let’s try it out:

val aiComponent: AIComponent = getAiComponent()

// this should be cached statically
val access = FieldAccess.get(AIComponent::class.java)
val fieldIndex = access.getIndex("steerable")

// call this in reset()
access.set(aiComponent, fieldIndex, null)

And finally, this is how we achieve nullable lateinit:

class AIComponent : PooledComponent {
    lateinit var steerable: SteerableEntity
    
    override fun reset() {
        nullifyThings(this)
    }

    object companion {
        val steerableFieldAccess = FieldAccess.get(AIComponent::class.java)
        val steerableFieldIndex = access.getIndex("steerable")

        fun nullifyThings(obj: AIComponent) {
            steerableFieldAccess.set(obj, steerableFieldIndex, null)
        }
    }
}

If you have to do this in a performant way, that’s a choice. I don’t expect to find a quicker way than with cached bytecode.

References

gamedev, Get Noticed 2017, kotlin
comments powered by Disqus