ret : return from subroutine : index : visitInsn()

Description
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 method
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) .
See also
jsr jsr_w goto goto_w wide
Stack
Before After
... ...
Bytecode
Type Description
u1 ret opcode = 0xA9 (169)
u1 <varnum>
There is also a wide format for this instruction, which supports access to all local variables from 0 to 65535:
Type Description
u1 wide opcode = 0xC4 (196)
u1 ret opcode = 0xA9 (169)
u2 <varnum>