Как лямбда-выражения переводятся в байт-код Java

Я пытаюсь создать пример с использованием лямбда-выражения в Java, и я использую официальный JDK8. Мой пример был успешно выполнен. Но когда я пытаюсь проверить, как компилятор переводит лямбда-выражение в байт-код, это вызывает у меня некоторую путаницу. Ниже приведен код моего примера:

public class LambdaTest {
    public Integer lambdaBinaryOpertor(BinaryOperator<Integer> binaryOperator) {
        return binaryOperator.apply(60, 72);
    }

    public static void main(String[] args) {
        LambdaTest test = new LambdaTest();
        BinaryOperator<Integer> binaryOperator = (a, b) -> a*b;
        System.out.println("Additon using Lambda BinaryOperator: "+test.lambdaBinaryOpertor(binaryOperator));
    }
}

В этой статье они обсуждают, как компилятор переводит лямбда-выражения в байт-код. Согласно этому документу лямбда-выражение конвертируется в static метод и место, где объявляется лямбда-выражение, имеют ссылку на лямбду static метод. Следующий пример в статье:

//Source code
class A {
    public void foo() {
        List<String> list = ...
        list.forEach( s -> { System.out.println(s); } );
    }
} 

//After compile above code "translate code " 
class A {
    public void foo() {
        List<String> list = ...
        list.forEach( [lambda for lambda$1 as Block] );
    }

    static void lambda$1(String s) {
        System.out.println(s);
    }
}

Мой пример работает нормально и дает нам соответствующий результат. Но когда я пытаюсь запустить javap Команда для проверки байтового кода класса, в байтовом коде нет статического метода для лямбда-выражений.

c:\>javap LambdaTest
Compiled from "LambdaTest.java"
public class LambdaTest {
public LambdaTest();
public java.lang.Integer lambdaBinaryOpertor(java.util.function.BinaryOperator <java.lang.Integer>);
public static void main(java.lang.String[]);
}

В случае обобщения, метод моста создается компилятором, и мы также проверим этот метод, используя javap команда, но в случае с лямбдами нет static метод. Статья была опубликована в 2012 году, а Java 8 была запущена в марте 2014 года. Итак, у меня есть несколько вопросов, касающихся транснациональной лямбда:

  1. Есть ли какая-либо новая реализация, используемая для лямбды в JDK 8 после выпуска этой статьи, или я сделаю что-то не так, чтобы проверить лямбда-метод?
  2. Как на самом деле компилятор справляется с лямбда-выражением?
  3. Как JVM вызывает лямбда-выражение?

1 ответ

Решение

Используйте дополнительные аргументы javap для вывода полной информации о классе: javap -v -p -s -c

Для вашего примера, исходный код лямбда будет:

private static java.lang.Integer lambda$main$0(java.lang.Integer, java.lang.Integer);
    descriptor: (Ljava/lang/Integer;Ljava/lang/Integer;)Ljava/lang/Integer;
    flags: ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC
    Code:
      stack=2, locals=2, args_size=2
         0: aload_0       
         1: invokevirtual #17                 // Method java/lang/Integer.intValue:()I
         4: aload_1       
         5: invokevirtual #17                 // Method java/lang/Integer.intValue:()I
         8: imul          
         9: invokestatic  #2                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
        12: areturn       
      LineNumberTable:
        line 10: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      13     0     a   Ljava/lang/Integer;
            0      13     1     b   Ljava/lang/Integer;
}
Другие вопросы по тегам