This document describes the production patterns for byte code by the jdk 1.4.2 compiler.

An if statement is compiled as follows:
        cond(A) block A
An if-else statement is compiled as follows:
        cond(A) block goto(B) A block B
        aload         // Load object reference.
        dup           // Duplicate object reference.
        getfield      // Fetch field oldValue.
        delta         // Can be any value, could even be an expression.
        add/sub       // Increment/decrement value.
                      // Stack: ref newValue
        dup_x1        // Duplicate top and put it on third position.
                      // Stack: newValue ref newValue.
        putfield      // Store field value.
                      // Stack: newValue
Reduction: ++field, --field, or (field = field + delta), if delta not equal to constant +/-1.
        aload         // Load object reference.
        dup           // Duplicate object reference.
        getfield      // Fetch field value.
                      // Stack: ref oldValue
        dup_x1        // Duplicate top and put it on third position.
                      // Stack: oldValue ref oldValue
        const         // Must be constant +/-1.
        add/sub       // Increment/decrement value.
                      // Stack: oldValue ref newValue
        putfield      // Store field value.
                      // Stack: oldValue.
Reduction: field++ or field--.
        iinc(delta)   // Increment variable.
        load          // Load variable.
                      // Stack: newValue
        load          // Load variable. 
        delta         // Any expression.
        add           // Increment.
        dup           // Stack: newValue newValue
        store         // Store to variable.
                      // Stack: newValue
	 load          // Load variable.
	 iinc(delta)   // Increment variable.
	 // Stack: oldValue

Note that we could match the pattern [load, iinc, load] with either (E) [i++, i] or (C) [i, ++i]. Of these obviously equivalent alternatives we choose (E).

    While statement:
       goto(B) A block B cond(A)
    Do statement:
       A block cond(A)
      
    For statement (equivalent to a do statement):
       init A block increment cond(A)
      

In Java, a try statement has the following structure:

               try Block Catch* (Catch | Finally)
      
A try block with finally clause has the following structure:
    TryCatchFinally:
        tryBlock 
        Handler  // 0..n times
        DefaultHandler
        B Finally 
        A jsr(B) 
	
Each time the control flow exits the try block or one of the non-default handlers, a jsr(B) is prepended. If the try block or one of the non-default handlers are exited by default (fall-through), then a goto(A) is appended at the end of the block.
There must be at least one handler. All handlers are non-default. Typically, goreth is a goto(A), but this must not be the case.
    TryCatchFinally:
        tryBlock goreth  
        Handler goreth  // 0..n
        Handler
        A
	
    DefaultHandler: (Any Exception)
        astore_exception jsr(B) aload_exception athrow
      
    Handler:
        astore_exception catchBlock
      
    Finally:
        astore_address finallyBlock ret
      

The store operations in the handlers save the exception to a local variable, whereas the store operation at the beginning of the subroutine saves the return address to local variable.

For each catch block, a codeException(BeginPC, EndPC, HandlerPC) is recorded, where HandlerPC = begin(Default?Handler) and

  1. BeginPC = begin(tryBlock), EndPC = begin(first Handler)-1, i.e. including the goto(A) for each non-default handler, or both
  2. BeginPC = begin(tryBlock), EndPC = end(last Handler) and
  3. BeginPC = A = begin(Tail), EndPC = end(Tail) for the default handler.

Note that from the byte code we cannot deduce the end of the last catch clause in the absense of a finally clause. This is also manifested by the equivalence of the following two Java code fracments:

    foo: {
        try {
           A;
           break foo;
        } catch(e) {
           B;
        }
        C;
    }
    
    foo: {
        try {
           A;
           break foo;
        } catch(e) {
           B;
           C;
        }
    }
      

Last modified: Sat Oct 15 20:44:54 Westeuropäische Sommerzeit 2005