Как лямбда-выражения переводятся в байт-код 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 года. Итак, у меня есть несколько вопросов, касающихся транснациональной лямбда:
- Есть ли какая-либо новая реализация, используемая для лямбды в JDK 8 после выпуска этой статьи, или я сделаю что-то не так, чтобы проверить лямбда-метод?
- Как на самом деле компилятор справляется с лямбда-выражением?
- Как 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;
}