ret <varnum> or wide ret <varnum>In the first form, <varnum> is an unsigned integer in the range 0 to 0xFF. In the second (wide) form, <varnum> is an unsigned integer in the range 0 to 0xFFFF.
Stack Before
Description After ... ...
ret is used to return from a subroutine that was invoked by jsr or jsr_w. It takes a single parameter, <varnum>, an unsigned integer which local variable is holding the returnAddress for this subroutine. Execution continues at the address stored in that local variable.
Return addresses are left on the stack by the jsr and jsr_w instructions. Methods are expected to immediately store the return address in a local variable, ready for use with ret.
Example
; This example method uses a PrintMe subroutine to invoke the System.out.println() method. .method usingSubroutine()V ldc "Message 1" jsr PrintMe ; print "Message 1" ldc "Message 2" jsr PrintMe ; print "Message 2" ldc "Message 3" jsr PrintMe ; print "Message 3" return ; now return from usingSubroutine ; define the PrintMe subroutine ... PrintMe: astore_1 ; store return-address in local variable 1 ; call System.out.println() getstatic java/lang/System/out Ljava/io/PrintStream; invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V ret 1 ; return to the return-address in local variable 1 .end methodBytecode
For local variable numbers in the range 0-255, use:
Type | Description |
u1 | ret opcode = 0xA9 (169) |
u1 | <varnum> |
Type | Description |
u1 | wide opcode = 0xC4 (196) |
u1 | ret opcode = 0xA9 (169) |
u2 | <varnum> |
jsr, jsr_w, goto, goto_w, wide
Notes
The assymetry between jsr (which pushes a returnAddress onto the stack) and ret (which gets the returnAddress from a local variable) is intentional - the bytecode verifier relies on this structure (see Chapter 5) .