Скомпилируйте следующий код с помощью компилятора ECJ из пакета Eclipse Mars.2:
import java.util.stream.*;
public class Test {
String test(Stream<?> s) {
return s.collect(Collector.of(() -> "", (a, t) -> {}, (a1, a2) -> a1));
}
}
Команда компиляции следующая:
$ java -jar org.eclipse.jdt.core_3.11.2.v20160128-0629.jar -8 -g Test.java
После успешной компиляции позвольте проверить полученный файл класса с помощью javap -v -p Test.class
. Наиболее интересным является синтетический метод, сгенерированный для (a, t) -> {}
lambda:
private static void lambda$1(java.lang.String, java.lang.Object);
descriptor: (Ljava/lang/String;Ljava/lang/Object;)V
flags: ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC
Code:
stack=0, locals=2, args_size=2
0: return
LineNumberTable:
line 5: 0
LocalVariableTable:
Start Length Slot Name Signature
0 1 0 a Ljava/lang/String;
0 1 1 t Ljava/lang/Object;
LocalVariableTypeTable:
Start Length Slot Name Signature
0 1 1 t !*
Я был очень удивлен, увидев эту запись !*
в LocalVariableTypeTable
. Спецификация JVM охватывает атрибут LocalVariableTypeTable и говорит:
Запись
constant_pool
в этом индексе должна содержать структуруCONSTANT_Utf8_info
(§4.4.7), представляющую сигнатуру поля, которая кодирует тип локальной переменной в исходной программе (§4.7.9.1).
§4.7.9.1 определяет грамматику для сигнатур поля, которая, если я правильно понимаю, не охватывает ничего похожего на !*
.
Следует также отметить, что ни javac-компилятор, ни старые версии ECJ 3.10.x не генерируют эту запись LocalVariableTypeTable
. Является ли !*
некоторым нестандартным расширением Eclipse или я что-то пропускаю в спецификации JVM? Означает ли это, что ECJ не соответствует спецификации JVM? Что означает !*
и есть ли другие подобные строки, которые могут появляться в атрибуте LocalVariableTypeTable
?