Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why Kotlin decompiler generates null.INSTANCE

I am trying to understand few of the Kotlin features by checking how it looks in Java side.

So as an experiment, I tried with this:

val printKotlin = fun () {
    print("Hello Kotlin")
}

So the output for the above snippet is:

public final class FunAsVariableKt {
    private static final Function0 printKotlin;

    public static final Function0 getPrintKotlin() {
        return printKotlin;
    }

    static {
        printKotlin = (Function0)null.INSTANCE;
    }
}

How do I understand the static block of the above decompiled code? Why it is generating this non working code?

like image 592
Chandra Sekhar Avatar asked Feb 04 '26 23:02

Chandra Sekhar


1 Answers

Use the Kotlin bytecode inspector to see what is being generated as JVM bytecode rather than trying to decompile bytecode to Java, which likely won't work for code generated by a different language compiler because it might not follow the expected patterns. A bytecode decompiler does not always generate working code.

JVM bytecode != Java language specific

Kotlin generated JVM bytecode != Java generated JVM bytecode

The NULL instance you are seeing is a misinterpretation by your decompiler, and you can see all references to INSTANCE in the bytecode are setting values correctly.

This is the actual output:

// ================Stackoverflow_53384931Kt.class =================
// class version 52.0 (52)
// access flags 0x31
public final class Stackoverflow_53384931Kt {


  // access flags 0x1A
  // signature Lkotlin/jvm/functions/Function0<Lkotlin/Unit;>;
  // declaration: kotlin.jvm.functions.Function0<kotlin.Unit>
  private final static Lkotlin/jvm/functions/Function0; printKotlin
  @Lorg/jetbrains/annotations/NotNull;() // invisible

  // access flags 0x19
  // signature ()Lkotlin/jvm/functions/Function0<Lkotlin/Unit;>;
  // declaration: kotlin.jvm.functions.Function0<kotlin.Unit> getPrintKotlin()
  public final static getPrintKotlin()Lkotlin/jvm/functions/Function0;
  @Lorg/jetbrains/annotations/NotNull;() // invisible
   L0
    LINENUMBER 3 L0
    GETSTATIC Stackoverflow_53384931Kt.printKotlin : Lkotlin/jvm/functions/Function0;
    ARETURN
   L1
    MAXSTACK = 1
    MAXLOCALS = 0

  // access flags 0x8
  static <clinit>()V
   L0
    LINENUMBER 3 L0
    GETSTATIC Stackoverflow_53384931Kt$printKotlin$1.INSTANCE : LStackoverflow_53384931Kt$printKotlin$1;
    CHECKCAST kotlin/jvm/functions/Function0
    PUTSTATIC Stackoverflow_53384931Kt.printKotlin : Lkotlin/jvm/functions/Function0;
    RETURN
    MAXSTACK = 1
    MAXLOCALS = 0

  @Lkotlin/Metadata; ... 
  // access flags 0x18
  final static INNERCLASS Stackoverflow_53384931Kt$printKotlin$1 null null
  // compiled from: stackoverflow-53384931.kt
}


// ================Stackoverflow_53384931Kt$printKotlin$1.class =================
// class version 52.0 (52)
// access flags 0x30
// signature Lkotlin/jvm/internal/Lambda;Lkotlin/jvm/functions/Function0<Lkotlin/Unit;>;
// declaration: Stackoverflow_53384931Kt$printKotlin$1 extends kotlin.jvm.internal.Lambda implements kotlin.jvm.functions.Function0<kotlin.Unit>
final class Stackoverflow_53384931Kt$printKotlin$1 extends kotlin/jvm/internal/Lambda  implements kotlin/jvm/functions/Function0  {


  // access flags 0x1041
  public synthetic bridge invoke()Ljava/lang/Object;
    ALOAD 0
    INVOKEVIRTUAL Stackoverflow_53384931Kt$printKotlin$1.invoke ()V
    GETSTATIC kotlin/Unit.INSTANCE : Lkotlin/Unit;
    ARETURN
    MAXSTACK = 1
    MAXLOCALS = 1

  // access flags 0x11
  public final invoke()V
   L0
    LINENUMBER 4 L0
    LDC "Hello Kotlin"
    ASTORE 1
   L1
    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
    ALOAD 1
    INVOKEVIRTUAL java/io/PrintStream.print (Ljava/lang/Object;)V
   L2
   L3
    LINENUMBER 5 L3
    RETURN
   L4
    LOCALVARIABLE this LStackoverflow_53384931Kt$printKotlin$1; L0 L4 0
    MAXSTACK = 2
    MAXLOCALS = 2

  // access flags 0x0
  <init>()V
    ALOAD 0
    ICONST_0
    INVOKESPECIAL kotlin/jvm/internal/Lambda.<init> (I)V
    RETURN
    MAXSTACK = 2
    MAXLOCALS = 1

  // access flags 0x19
  public final static LStackoverflow_53384931Kt$printKotlin$1; INSTANCE

  // access flags 0x8
  static <clinit>()V
    NEW Stackoverflow_53384931Kt$printKotlin$1
    DUP
    INVOKESPECIAL Stackoverflow_53384931Kt$printKotlin$1.<init> ()V
    PUTSTATIC Stackoverflow_53384931Kt$printKotlin$1.INSTANCE : LStackoverflow_53384931Kt$printKotlin$1;
    RETURN
    MAXSTACK = 2
    MAXLOCALS = 0

  @Lkotlin/Metadata; ...
  OUTERCLASS Stackoverflow_53384931Kt null
  // access flags 0x18
  final static INNERCLASS Stackoverflow_53384931Kt$printKotlin$1 null null
  // compiled from: stackoverflow-53384931.kt
  // debug info: SMAP
  ...

}
like image 199
Jayson Minard Avatar answered Feb 06 '26 14:02

Jayson Minard



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!