Ошибка проверки JVM «Недопустимый тип в постоянном пуле»

В настоящее время я пишу свой собственный компилятор и пытаюсь скомпилировать следующий код:

List[String] list = List("a", "b", "c", "d")
list stream map((String s) => s.toUpperCase())
System out println list

У компилятора нет проблем с синтаксическим анализом, компоновкой или компиляцией кода, но когда дело доходит до его выполнения, JVM выдает следующую ошибку:

java.lang.VerifyError: Illegal type at constant pool entry 40 in class dyvil.test.Main
Exception Details:
  Location:
    dyvil/test/Main.main([Ljava/lang/String;)V @29: invokevirtual
  Reason:
    Constant pool index 40 is invalid
  Bytecode:
    ...

Я пробовал использовать javap, чтобы найти проблему, и это инструкция @29:

29: invokevirtual #40 // InterfaceMethod java/util/Collection.stream:()Ljava/util/stream/Stream;

И запись в постоянном пуле (также с использованием javap):

#37 = Utf8               stream
#38 = Utf8               ()Ljava/util/stream/Stream;
#39 = NameAndType        #37:#38 // stream:()Ljava/util/stream/Stream;
#40 = InterfaceMethodref #36.#39 // java/util/Collection.stream:()Ljava/util/stream/Stream;

При открытии класса с помощью средства просмотра файлов классов Eclipse строка, где должно быть указано @29:

Class Format Exception

и все следующие инструкции больше не отображаются (кроме Locals, ...). Однако плагин байт-кода ASM пишет

INVOKEVIRTUAL java/util/Collection.stream ()Ljava/util/stream/Stream;

в этой строке, которая кажется действительной. Что я здесь делаю не так / не хватает?


person Clashsoft    schedule 23.02.2015    source источник


Ответы (2)


Я понял свою ошибку. Ошибка здесь:

invokevirtual #40 // InterfaceMethod
      ^^^^^^^        ^^^^^^^^^

Я использую invoke virtual в методе интерфейса, что, как правило, не является хорошей идеей. Однако я думаю, что ошибка, выданная верификатором, должна быть немного более ясной в отношении того, что на самом деле не так.

person Clashsoft    schedule 23.02.2015
comment
Возможно, стоит сообщить об ошибке компилятора. - person Hot Licks; 23.02.2015
comment
О, я вижу, что это ваш компилятор, а не javac. В этом случае отправьте отчет об ошибке себе. - person Hot Licks; 23.02.2015

В ASM вы увидите эту ошибку из-за неправильного флага isInterface. Аргумент isInterface из visitMethodInsn относится к цели / владельцу / получателю, а не к текущему контексту.

i.o.w при использовании INVOKEVIRTUAL, isInterface ложно.

см. здесь для получения дополнительных сведений.

person nickl-    schedule 25.05.2018