6

When being Lazy pays off: Kotlin Objects and NoClassDefFoundError

 1 year ago
source link: https://blog.davidvassallo.me/2023/02/27/when-being-lazy-pays-off-kotlin-objects-and-noclassdeffounderror/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

When being Lazy pays off: Kotlin Objects and NoClassDefFoundError

One of my favorite concepts in Kotlin is the “Object” class. A quick refresh:

A normal “class“:

class ExampleClass(arg1: String)

An “object” is very similar in syntax as can be seen below, but comes with a crucial difference: it is a singleton.

object ExampleObject

There’s a lot of debate around Singletons being evil or not… but if you use them, in Kotlin the best way to express them is using an object. So you might be tempted to define a singleton object containing your database connection, like this:

object ExampleObject {
val db = SomeDbDriver.GetConnection("db_connection_string")
}

Looks great… a singleton which allows you to access your expensive DB connection via a simple ExampleObject.db call. But this is a trap, which is not always sprung.

The pitfall here is that you may occasionally see errors complaining of NoClassDefFoundError for “ExampleObject” in our example above.

A really good explainer of why this happens in general can be found here:

https://stackoverflow.com/questions/75067109/java-lang-noclassdeffounderror-could-not-initialize-class-com-blacklight-common

The key quote from that article is:

This means that we previously attempted to load a class from the classpath, but it failed for some reason – now we’re trying to use the class again (and thus need to load it, since it failed last time), but we’re not even going to try to load it, because we failed loading it earlier (and reasonably suspect that we would fail again).

https://stackoverflow.com/questions/75067109/java-lang-noclassdeffounderror-could-not-initialize-class-com-blacklight-common

In our example above…. your database might be heavily loaded when the compiled program is first run, so object initialization will fail.. leading to a NoClassDefFoundError for the rest of the program lifetime. To avoid this, make use of Kotlin’s lazy loading operators, and modify our object code to:

object ExampleObject {
val db by lazy {
SomeDbDriver.GetConnection("db_connection_string")
}
}

This will make sure that the value is not initialized until required AND that it will try to be intialized everytime it is accessed, and not fail with a NoClassDefFoundError if it fails the first time (which arguably is a lousy error message to get that doesnt quite hint at what happened… unless you read the SO answer I linked to above). This is my preferred syntax since it makes the intent clear, but using the init block of an object should also have the same effect


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK