     # instructions obviate the need for one
     unless op.offset? or (op.name.indexOf 'return') != -1
       @add_stmt => @compile_epilogue()
+
+    # catch any try blocks
+    if (handler = @has_try)?
+      next_block = @block_chain.get_block_from_instr handler.handler_pc
+      @add_stmt """
+        } catch (e) {
+          if (!(e instanceof util.JavaException)) throw e
+      """
+      if handler.catch_type == "<any>"
+        @add_stmt "rs.push(e.exception); label = #{handler.handler_pc}; continue\n}"
+      else
+        @add_stmt """
+          if (types.is_castable(rs, e.exception.type, types.c2t(#{JSON.stringify handler.catch_type}))) {
+            rs.push(e.exception); label = #{handler.handler_pc}; continue;
+          } else {
+            throw e;
+          }\n}
+        """
+      next_block.stack = ["rs.pop()"]
+      next_block.compile @stack, @locals, true
 
     for next_block in @next
       # java bytecode verification ensures that the stack height and stack /

    method.code.each_opcode (idx, oc) =>
      current_block++ if idx in labels
      block = @blocks[current_block]
      block.opcodes.push oc

    @param_names = ['rs']

        b.push temp

compile_obj_handlers = {
  # pseudo-opcode, generates the beginning of a try block
  'try': { compile: (b) -> b.add_stmt "try { //" }
  aconst_null: { compile: (b) -> b.push new Primitive "null"; }
  iconst_m1: { compile: (b) -> b.push new Primitive "-1"; }
  iconst_0: { compile: (b) -> b.push new Primitive "0"; }
