1

I've got the following code that gives an error when ran with the 2 print statements but when I only do one it runs fine. If I'm correct ldc just pushes the string on the stack, so while invoking the second printline it should still have something on stack.

.class public test
.super java/lang/Object

.method public static main([Ljava/lang/String;)V
.limit stack 5
.limit locals 3

getstatic java/lang/System/out Ljava/io/PrintStream;
ldc "this would work if only this line was printed"
invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V
ldc "but when trying to print this it says it's not on stack?"
invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V
return
.end method

Error:

java.lang.VerifyError: (class: test, method: main signature: ([Ljava/lang/String;)V) Unable to pop operand off an empty stack
        at java.lang.Class.getDeclaredMethods0(Native Method)
        at java.lang.Class.privateGetDeclaredMethods(Unknown Source)
        at java.lang.Class.privateGetMethodRecursive(Unknown Source)
        at java.lang.Class.getMethod0(Unknown Source)
        at java.lang.Class.getMethod(Unknown Source)
        at sun.launcher.LauncherHelper.validateMainClass(Unknown Source)
        at sun.launcher.LauncherHelper.checkAndLoadMain(Unknown Source)
Error: A JNI error has occurred, please check your installation and try again
Exception in thread "main"
  • 3
    To perform `invokevirtual`, you need an object to invoke the method on, also known as *method receiver*. Like the `PrintStream` you are pushing with `getstatic`. To perform two `invokevirtual` instructions, you need not only two arguments, but also two receivers. – Holger May 07 '20 at 10:31
  • So I would have to add the line `getstatic java/lang/System/out Ljava/io/PrintStream;` again before invoking printstream the second time? –  May 07 '20 at 10:49
  • 2
    That’s one way (the simplest) to achieve this. Just follow the `getstatic, ldc, invokevirtual` pattern two times. Like `System.out.println("one"); System.out.println("two");` would do in source code. Or create the equivalent to `PrintStream tmp = System.out; tmp.println("one"); tmp.println("two");`. – Holger May 07 '20 at 10:52
  • Thanks, that works. Do you have any sources on jasmin documentation? I'm currently using [the offical jasmin instructions](http://jasmin.sourceforge.net/instructions.html) but often find them very vague or incomplete. –  May 07 '20 at 11:05
  • 2
    I'd recommend just reading the JVM specification. – Antimony May 07 '20 at 11:47
  • 1
    @Sten The “(c) …July 1996” on that page should tell you something. As said at the answer to your other question, Jasmin has not been updated for a decade (in fact, sourceforge does not even support updates anymore, due to the outdated CVS repository). You are riding a dead horse here. [The Java® Virtual Machine Specification](https://docs.oracle.com/javase/specs/jvms/se12/html/index.html) contains everything you need to know. But keep in mind that a) there is no official standard regarding assembly syntax so Jasmin may have subtle differences and b) Jasmin won’t support newer features. – Holger May 07 '20 at 11:54

0 Answers0