Search code examples
kotlinlockingsynchronized

kotlin, why decompiled java code translate the synchronized lock block into synchronized(var1){} + code block?


in kotlin, there is synchronized block

synchronized(_lock) {
  // code do something
}

it meant to release the lock until all // code fo something is done.

but in the decompiled java code the synchronized(lock) block is put outside of the code block

Object var1 = this._lock;
synchronized(var1){}
// code do something

, does it mean that the lock will be released too earlier that the // code fo something might be still running?

kotlin code:

override fun doSomething(): Boolean {
  synchronized(_lock) {

     //......


     lastCompleteAt = Date().time + REQUEST_THROTTLE_TIME

     for ((_, handler) in dataRequestMap) {

        //......
     }
     return true
  }
   }

decompiled to java code:

public boolean doSomething() {

  Object var1 = this._lock;
  synchronized(var1){}

  boolean var7;
  try {
     //......


     this.lastCompleteAt = (new Date()).getTime() + 5000L;
     Map var3 = (Map)this.dataRequestMap;
     Iterator var4 = var3.entrySet().iterator();

     while(var4.hasNext()) {

        //......
     }

     //......
     var7 = true;
  } finally {
     ;
  }

  return var7;
}

Solution

  • I believe @tkausl is correct in that your decompiler simply decompiled the code incorrectly. If you inspect the byte code generated by the following:

    fun main() {
        val lock = Any()
        synchronized(lock) {
            println("Hello, World!")
        }
    }
    

    You'll see:

    Compiled from "Main.kt"
    public final class MainKt {
      public static final void main();
        Code:
           0: new           #4                  // class java/lang/Object
           3: dup
           4: invokespecial #12                 // Method java/lang/Object."<init>":()V
           7: astore_0
           8: iconst_0
           9: istore_1
          10: iconst_0
          11: istore_2
          12: aload_0
          13: monitorenter
          14: nop
          15: iconst_0
          16: istore_3
          17: ldc           #14                 // String Hello, World!
          19: astore        4
          21: iconst_0
          22: istore        5
          24: getstatic     #20                 // Field java/lang/System.out:Ljava/io/PrintStream;
          27: aload         4
          29: invokevirtual #26                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
          32: getstatic     #32                 // Field kotlin/Unit.INSTANCE:Lkotlin/Unit;
          35: astore_2
          36: aload_0
          37: monitorexit
          38: goto          46
          41: astore_2
          42: aload_0
          43: monitorexit
          44: aload_2
          45: athrow
          46: return
        Exception table:
           from    to  target type
              14    36    41   any
              41    42    41   any
    
      public static void main(java.lang.String[]);
        Code:
           0: invokestatic  #9                  // Method main:()V
           3: return
    }
    

    If you notice, there is a "monitorenter" command (13) before the println("Hello, World") statement (29), followed by a "monitorexit" command (37).