使用 Eclipse 编译器编译时,LocalVariableTypeTable 中奇怪的 “!*” 条目
让我们使用 Eclipse Mars.2 捆绑包中的 ECJ 编译器编译以下代码:
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
编译成功后,让我们使用 检查生成的类文件。最有趣的是为lambda生成的合成方法:javap -v -p Test.class
(a, t) -> {}
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 !*
我很惊讶地看到这个条目。JVM规范涵盖了LocalVariableTypeTable属性,并说:!*
LocalVariableTypeTable
该索引处的条目必须包含一个结构 (§4.4.7),该结构表示对源程序中局部变量的类型进行编码的字段签名 (§4.7.9.1)。
constant_pool
CONSTANT_Utf8_info
§4.7.9.1 定义了字段签名的语法,如果我理解正确,它不包括与 .!*
还应该注意的是,javac编译器和较旧的ECJ 3.10.x版本都不会生成此条目。是一些非标准的Eclipse扩展,或者我在JVM规范中缺少一些东西?这是否意味着 ECJ 不符合 JVM 规范?实际上是什么意思,是否有任何其他类似的字符串可以出现在属性中?LocalVariableTypeTable
!*
!*
LocalVariableTypeTable