Почему Kotlin декомпилятор генерирует ноль. - PullRequest
0 голосов
/ 20 ноября 2018

Я пытаюсь понять некоторые особенности Kotlin, проверяя, как это выглядит на стороне Java.

Так что в качестве эксперимента я попробовал с этим:

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

Таким образом, вывод для приведенного выше фрагмента:

public final class FunAsVariableKt {
    private static final Function0 printKotlin;

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

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

Как я понимаю статический блок вышеупомянутого декомпилированного кода? Почему он генерирует этот нерабочий код?

1 Ответ

0 голосов
/ 20 ноября 2018

Используйте инспектор байт-кода Kotlin, чтобы увидеть, что генерируется как байт-код JVM, а не пытаться декомпилировать байт-код в Java, что, скорее всего, не будет работать для кода, сгенерированного компилятором другого языка, поскольку он может не соответствовать ожидаемым шаблонам. Декомпилятор байт-кода не всегда генерирует рабочий код.

Байт-код JVM! = Специфический для языка Java

Сгенерированный Kotlin байт-код JVM! = Java сгенерированный байт-код JVM

Экземпляр NULL, который вы видите, неверно интерпретируется вашим декомпилятором, и вы видите, что все ссылки на INSTANCE в байт-коде правильно устанавливают значения.

Это фактический результат:

// ================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
  ...

}
...