Java 字节码,调用方法不正常
Java byte code, calling method is not working properly
现状与背景
对于一项学校作业,我们必须编写自己的编程语言。目前,我一直在尝试进行方法调用。
我可以成功创建一个方法,但是在我尝试调用它的时候,程序中断了。
测试代码
我用来测试的代码是
testMethod();
method testMethod () {
print("Test");
}
这将生成以下代码
- 反编译class
//
// 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(String[] param0) {
// $FF: Couldn't be decompiled
}
public void testMethod() {
System.out.println("Test");
}
}
- Java字节码
.class public test
.super java/lang/Object
.method public static main([Ljava/lang/String;)V
.limit stack 99
.limit locals 99
invokevirtual void/testMethod()V
return
.end method
.method public testMethod()V
getstatic java/lang/System/out Ljava/io/PrintStream;
ldc "Test"
invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V
.limit stack 10
.limit locals 10
return
.end method
我尝试了什么
我尝试使用以下 Java 字节代码调用该方法:
(test 是我正在测试的 class 的名称)
- 调用虚拟 void/testMethod()V
- 调用虚拟测试方法()V
- 调用虚拟 test/testMethod()V
- 调用虚拟测试/void/testMethod()V
感谢任何帮助
正如@apangin 在评论中所解释的那样,您正在尝试调用一个实例方法,因此您需要一个对象来调用它,但您没有提供一个对象。您需要创建一个 test
实例并在调用 testMethod
之前将其压入堆栈,或者将 testMethod
标记为静态并通过 invokestatic
调用它,这可能更容易在这种情况下。
也就是说,我也建议使用 Krakatau assembler 而不是 Jasmin。 Krakatau 使用 Jasmin 语法的略微修改形式,它更简单且不易出错。特别是,在 Krakatau 中,class 名称、方法名称和方法描述符由空格分隔,消除了您对调用方法时需要在何处放置斜杠的困惑。 Krakatau 还具有其他优势,例如完全支持字节码格式,包括 Java 14 个功能,以及往返反汇编程序,极大地帮助解决字节码相关问题。
现状与背景
对于一项学校作业,我们必须编写自己的编程语言。目前,我一直在尝试进行方法调用。
我可以成功创建一个方法,但是在我尝试调用它的时候,程序中断了。
测试代码
我用来测试的代码是
testMethod();
method testMethod () {
print("Test");
}
这将生成以下代码
- 反编译class
//
// 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(String[] param0) {
// $FF: Couldn't be decompiled
}
public void testMethod() {
System.out.println("Test");
}
}
- Java字节码
.class public test
.super java/lang/Object
.method public static main([Ljava/lang/String;)V
.limit stack 99
.limit locals 99
invokevirtual void/testMethod()V
return
.end method
.method public testMethod()V
getstatic java/lang/System/out Ljava/io/PrintStream;
ldc "Test"
invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V
.limit stack 10
.limit locals 10
return
.end method
我尝试了什么
我尝试使用以下 Java 字节代码调用该方法:
(test 是我正在测试的 class 的名称)
- 调用虚拟 void/testMethod()V
- 调用虚拟测试方法()V
- 调用虚拟 test/testMethod()V
- 调用虚拟测试/void/testMethod()V
感谢任何帮助
正如@apangin 在评论中所解释的那样,您正在尝试调用一个实例方法,因此您需要一个对象来调用它,但您没有提供一个对象。您需要创建一个 test
实例并在调用 testMethod
之前将其压入堆栈,或者将 testMethod
标记为静态并通过 invokestatic
调用它,这可能更容易在这种情况下。
也就是说,我也建议使用 Krakatau assembler 而不是 Jasmin。 Krakatau 使用 Jasmin 语法的略微修改形式,它更简单且不易出错。特别是,在 Krakatau 中,class 名称、方法名称和方法描述符由空格分隔,消除了您对调用方法时需要在何处放置斜杠的困惑。 Krakatau 还具有其他优势,例如完全支持字节码格式,包括 Java 14 个功能,以及往返反汇编程序,极大地帮助解决字节码相关问题。