3

我在 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 OutlineEclipse Class Decompiler插件。

4

0 回答 0