我在 Eclipse 禁用导入二进制文件的 Java 类中的所有代码完成时遇到了严重问题。二进制文件由自定义编译器编译为基于 JVM 的自定义编程语言,代码如下所示:
package dyvil.dyn
import dyvil.lang.Map.Entry
public class Test[A, B] implements Entry[A, B]
{
public A getKey() = null
public B getValue() = null
}
Entry
是接口里面的一个Map
接口,都是Java写的。编译器显然对这段代码没有任何问题,并生成以下字节码(来自javap
):
public class dyvil.dyn.Test<A extends java.lang.Object, B extends java.lang.Object> extends java.lang.Object implements dyvil.lang.Map$Entry<A, B>
Signature: #3 // <A:Ljava/lang/Object;B:Ljava/lang/Object;>Ljava/lang/Object;Ldyvil/lang/Map$Entry<TA;TB;>;
InnerClasses:
public static #10= #7 of #9; //Entry=class dyvil/lang/Map$Entry of class dyvil/lang/Map
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Utf8 dyvil/dyn/Test
#2 = Class #1 // dyvil/dyn/Test
#3 = Utf8 <A:Ljava/lang/Object;B:Ljava/lang/Object;>Ljava/lang/Object;Ldyvil/lang/Map$Entry<TA;TB;>;
#4 = Utf8 java/lang/Object
#5 = Class #4 // java/lang/Object
#6 = Utf8 dyvil/lang/Map$Entry
#7 = Class #6 // dyvil/lang/Map$Entry
#8 = Utf8 dyvil/lang/Map
#9 = Class #8 // dyvil/lang/Map
#10 = Utf8 Entry
#11 = Utf8 <init>
#12 = Utf8 ()V
#13 = NameAndType #11:#12 // "<init>":()V
#14 = Methodref #5.#13 // java/lang/Object."<init>":()V
#15 = Utf8 this
#16 = Utf8 Ldyvil/dyn/Test<TA;TB;>;
#17 = Utf8 Ldyvil/dyn/Test;
#18 = Utf8 getKey
#19 = Utf8 ()Ljava/lang/Object;
#20 = Utf8 getValue
#21 = Utf8 Code
#22 = Utf8 LocalVariableTable
#23 = Utf8 LocalVariableTypeTable
#24 = Utf8 Signature
#25 = Utf8 ()TA;
#26 = Utf8 ()TB;
#27 = Utf8 InnerClasses
{
public dyvil.dyn.Test();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #14 // Method java/lang/Object."<init>":()V
4: return
LocalVariableTable:
Start Length Slot Name Signature
0 4 0 this Ldyvil/dyn/Test;
LocalVariableTypeTable:
Start Length Slot Name Signature
0 4 0 this Ldyvil/dyn/Test<TA;TB;>;
Signature: #12 // ()V
public A getKey();
descriptor: ()Ljava/lang/Object;
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aconst_null
1: areturn
LocalVariableTable:
Start Length Slot Name Signature
0 1 0 this Ldyvil/dyn/Test;
LocalVariableTypeTable:
Start Length Slot Name Signature
0 1 0 this Ldyvil/dyn/Test<TA;TB;>;
Signature: #25 // ()TA;
public B getValue();
descriptor: ()Ljava/lang/Object;
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aconst_null
1: areturn
LocalVariableTable:
Start Length Slot Name Signature
0 1 0 this Ldyvil/dyn/Test;
LocalVariableTypeTable:
Start Length Slot Name Signature
0 1 0 this Ldyvil/dyn/Test<TA;TB;>;
Signature: #26 // ()TB;
}
从任何 Java 类导入Test
该类会导致 Eclipse 抱怨No completions available
,并且CTRL-Hover
不再工作。为了找到问题,我创建并javap
编辑了上述类的 Java 等效项,产生以下结果:
测试.java:
package dyvil.test;
import dyvil.lang.Map.Entry;
public class Test<A, B> implements Entry<A, B>
{
@Override
public A getKey()
{
return null;
}
@Override
public B getValue()
{
return null;
}
}
javap输出:
public class dyvil.test.Test<A extends java.lang.Object, B extends java.lang.Object> extends java.lang.Object implements dyvil.lang.Map$Entry<A, B>
SourceFile: "Test.java"
Signature: #26 // <A:Ljava/lang/Object;B:Ljava/lang/Object;>Ljava/lang/Object;Ldyvil/lang/Map$Entry<TA;TB;>;
InnerClasses:
public static #30= #5 of #28; //Entry=class dyvil/lang/Map$Entry of class dyvil/lang/Map
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Class #2 // dyvil/test/Test
#2 = Utf8 dyvil/test/Test
#3 = Class #4 // java/lang/Object
#4 = Utf8 java/lang/Object
#5 = Class #6 // dyvil/lang/Map$Entry
#6 = Utf8 dyvil/lang/Map$Entry
#7 = Utf8 <init>
#8 = Utf8 ()V
#9 = Utf8 Code
#10 = Methodref #3.#11 // java/lang/Object."<init>":()V
#11 = NameAndType #7:#8 // "<init>":()V
#12 = Utf8 LineNumberTable
#13 = Utf8 LocalVariableTable
#14 = Utf8 this
#15 = Utf8 Ldyvil/test/Test;
#16 = Utf8 LocalVariableTypeTable
#17 = Utf8 Ldyvil/test/Test<TA;TB;>;
#18 = Utf8 getKey
#19 = Utf8 ()Ljava/lang/Object;
#20 = Utf8 Signature
#21 = Utf8 ()TA;
#22 = Utf8 getValue
#23 = Utf8 ()TB;
#24 = Utf8 SourceFile
#25 = Utf8 Test.java
#26 = Utf8 <A:Ljava/lang/Object;B:Ljava/lang/Object;>Ljava/lang/Object;Ldyvil/lang/Map$Entry<TA;TB;>;
#27 = Utf8 InnerClasses
#28 = Class #29 // dyvil/lang/Map
#29 = Utf8 dyvil/lang/Map
#30 = Utf8 Entry
{
public dyvil.test.Test();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #10 // Method java/lang/Object."<init>":()V
4: return
LineNumberTable:
line 5: 0
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this Ldyvil/test/Test;
LocalVariableTypeTable:
Start Length Slot Name Signature
0 5 0 this Ldyvil/test/Test<TA;TB;>;
public A getKey();
descriptor: ()Ljava/lang/Object;
flags: ACC_PUBLIC
Signature: #21 // ()TA;
Code:
stack=1, locals=1, args_size=1
0: aconst_null
1: areturn
LineNumberTable:
line 10: 0
LocalVariableTable:
Start Length Slot Name Signature
0 2 0 this Ldyvil/test/Test;
LocalVariableTypeTable:
Start Length Slot Name Signature
0 2 0 this Ldyvil/test/Test<TA;TB;>;
public B getValue();
descriptor: ()Ljava/lang/Object;
flags: ACC_PUBLIC
Signature: #23 // ()TB;
Code:
stack=1, locals=1, args_size=1
0: aconst_null
1: areturn
LineNumberTable:
line 16: 0
LocalVariableTable:
Start Length Slot Name Signature
0 2 0 this Ldyvil/test/Test;
LocalVariableTypeTable:
Start Length Slot Name Signature
0 2 0 this Ldyvil/test/Test<TA;TB;>;
}
我设法找到了由 class 引起的问题implements Entry[A, B]
,但我还无法识别字节码中的实际问题。我的编译器生成的字节码有什么问题吗?除了包名和行号之类的东西,我找不到两个类的字节码之间的显着差异。
如果这不是编译器的错,我只有ANTLR 4
,Bytecode Outline
和Eclipse Class Decompiler
插件。