Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is this a bug in Kotlin or I missing something?

I don't have to much experience in multi-threading. So not sure if I got right the following Java code decompiled from Kotlin.

Here is the Kotlin code:

companion object {
    @Volatile private var INSTANCE: SomeDatabase? = null

    fun getInstance(context: Context): SomeDatabase =
            INSTANCE ?: synchronized(this) {
                INSTANCE ?: buildDatabase(context).also { INSTANCE = it }
            }
}

Here is the decompiled code in Java:

     SomeDatabase var10000 = ((SomeDatabase.Companion)this).getINSTANCE();
     if (var10000 == null) {
        synchronized(this){}

        SomeDatabase var4;
        try {
           var10000 = SomeDatabase.Companion.getINSTANCE();
           if (var10000 == null) {

               ...

        var10000 = var4;
     }

     return var10000;

Doesn't this mean that code is actually not synchronized because of empty block in synchronized(this){}?

like image 472
oreh Avatar asked Jun 13 '18 19:06

oreh


1 Answers

If you look at the bytecode itself without decompiling it, you'll see that the synchronization happens as it should - this here is a version stripped of lots of load and store operations, line numbers, etc., but what matters is where the MONITORENTER and MONITOREXIT instructions are:

public final getInstance(Landroid/content/Context;)Lcom/example/SomeDatabase;
    LDC "context"
    INVOKESTATIC kotlin/jvm/internal/Intrinsics.checkParameterIsNotNull (Ljava/lang/Object;Ljava/lang/String;)V
    INVOKESTATIC com/example/Foo.access$getINSTANCE$cp ()Lcom/example/SomeDatabase;
    MONITORENTER
    INVOKESTATIC com/example/Foo.access$getINSTANCE$cp ()Lcom/example/SomeDatabase;
    INVOKESTATIC com/example/FooKt.buildDatabase (Landroid/content/Context;)Lcom/example/SomeDatabase;
    INVOKESTATIC com/example/Foo.access$setINSTANCE$cp (Lcom/example/SomeDatabase;)V
    MONITOREXIT
    MONITOREXIT
    ARETURN

The issue you're seeing is not a bug in the compiler, but rather an issue with the decompiler, which isn't particularly rare. It's quite the challenge to decompile arbitrary generated bytecode back to Java.

like image 192
zsmb13 Avatar answered Nov 07 '22 18:11

zsmb13