#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. Однако, является ли их использование допустимым решением для вашего назначения, зависит от назначения.