Search code examples
jvmbytecodejasmin

Java byte code, calling method is not working properly


Current situation & context

For a school assignment, we have to write our own programming language. Currently, I am stuck trying at the point of making a method call.

I can successfully make a method, but at the point where I am trying to call it, the program breaks.

Test code

The code that I am using to test is

testMethod();

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

This generates the following code

  • Decompiled 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 byte code
.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

What have I tried

I have tried to call the method with the following Java byte code:

(test is the name of the class where I am testing with)

  • invokevirtual void/testMethod()V
  • invokevirtual testMethod()V
  • invokevirtual test/testMethod()V
  • invokevirtual test/void/testMethod()V

I appreciate any help


Solution

  • As explained by @apangin in the comments, you are trying to call an instance method, so you need an object to call it on, but you did not supply one. You need to create a test instance and push it to the stack prior to calling testMethod, or alternatively mark testMethod as static and invoke it via invokestatic, which is probably easier in this case.

    That being said, I would also recommend using the Krakatau assembler rather than Jasmin. Krakatau uses a slightly modified form of Jasmin's syntax which is simpler and less error prone. In particular, in Krakatau, the class name, method name, and method descriptor are separated by spaces, removing a lot of the confusion you had about where you need to put the slashes when calling a method. Krakatau also has other advantages like full support for the bytecode format including Java 14 features, as well as a round trip disassembler which greatly assists with troubleshooting bytecode related issues.