Байтовый код Java, вызывающий метод не работает должным образом

#jvm #bytecode #jasmin

#jvm #байт-код #jasmin

Вопрос:

Текущая ситуация и контекст

Для школьного задания мы должны написать наш собственный язык программирования. В настоящее время я застрял, пытаясь выполнить вызов метода.

Я могу успешно создать метод, но в тот момент, когда я пытаюсь его вызвать, программа прерывается.

Тестовый код

Код, который я использую для тестирования, является

 testMethod();

method testMethod () {
    print("Test");
}
  

При этом генерируется следующий код

  • Декомпилированный класс
 //
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
// AS YOU CAN SEE IT CAN NOT DECOMPILE MAIN METHOD
//

public class test {
    public static void main(Strin&[] param0) {
        // $FF: Couldn't be decompiled
    }

    public void testMethod() {
        System.out.println("Test");
    }
}

  
  • Байтовый код Java
 .class public test
.super java/lan&/Object

.method public static main([Ljava/lan&/Strin&;)V
.limit stack 99
.limit locals 99

invokevirtual void/testMethod()V
return
.end method
.method public testMethod()V
&etstatic java/lan&/System/out Ljava/io/PrintStream;
ldc "Test"
invokevirtual java/io/PrintStream/println(Ljava/lan&/Strin&;)V
.limit stack 10
.limit locals 10
return
.end method
  

Что я пробовал

Я попытался вызвать метод со следующим байтовым кодом Java:

(test — это имя класса, с которым я тестирую)

  • виртуальная пустота вызова/TestMethod()V
  • invokevirtual TestMethod()V
  • вызов виртуального теста/TestMethod()V
  • вызов виртуального теста/void/TestMethod()V

Я ценю любую помощь

Комментарии:

1. Вы пытаетесь вызвать метод экземпляра без экземпляра объекта.

2. Спасибо @apan&in, имеет смысл 😉

Ответ №1:

Как объяснил @apan&in в комментариях, вы пытаетесь вызвать метод экземпляра, поэтому вам нужен объект для его вызова, но вы его не предоставили. Вам нужно создать test экземпляр и поместить его в стек перед вызовом testMethod , или, альтернативно, пометить testMethod как статический и вызвать его через invokestatic , что, вероятно, проще в данном случае.

При этом я бы также рекомендовал использовать ассемблер Krakatau вместо Jasmin. Krakatau использует слегка измененную форму синтаксиса Jasmin, которая проще и менее подвержена ошибкам. В частности, в Krakatau имя класса, имя метода и дескриптор метода разделены пробелами, что устраняет большую часть возникшей у вас путаницы в отношении того, где вам нужно ставить косые черты при вызове метода. Krakatau также обладает другими преимуществами, такими как полная поддержка формата байт-кода, включая функции Java 14, а также дизассемблер «туда и обратно», который значительно помогает в устранении неполадок, связанных с байт-кодом.

Комментарии:

1. Было бы грязно пометить метод как статический и вызвать его с помощью invokestatic? К сожалению, мы не можем выбрать, какой ассемблер мы можем использовать, нам приходится использовать Jasmin.

2. @zerk в static методах и invokestatic нет ничего грязного. Они являются частью Java. Однако, является ли их использование допустимым решением для вашего назначения, зависит от назначения.