--- old/src/share/vm/classfile/verifier.cpp 2015-03-13 13:30:07.653274000 -0400 +++ new/src/share/vm/classfile/verifier.cpp 2015-03-13 13:30:06.599912000 -0400 @@ -657,6 +657,7 @@ bool this_uninit = false; // Set to true when invokespecial initialized 'this' + bool verified_exc_handlers = false; // Merge with the next instruction { @@ -688,6 +689,17 @@ } } + // Look for possible jump target in exception handlers and see if it + // matches current_frame. Do this check here for astore* opcodes because + // they can both reference the exception object in a handler and change + // the type state. JVM Spec says that the incoming type state should be + // used for this check. + if (Bytecodes::is_astore(opcode) && bci >= ex_min && bci < ex_max) { + verify_exception_handler_targets( + bci, this_uninit, ¤t_frame, &stackmap_table, CHECK_VERIFY(this)); + verified_exc_handlers = true; + } + switch (opcode) { case Bytecodes::_nop : no_control_flow = false; break; @@ -1669,9 +1681,13 @@ } // end switch } // end Merge with the next instruction - // Look for possible jump target in exception handlers and see if it - // matches current_frame - if (bci >= ex_min && bci < ex_max) { + // Look for possible jump target in exception handlers and see if it matches + // current_frame. Don't do this check if it has already been done (for + // astore* opcodes). This check cannot be done earlier because opcodes, + // such as invokespecial, may set the this_uninit flag. + assert(!(verified_exc_handlers && this_uninit), + "Exception handler targets got verified before this_uninit got set"); + if (!verified_exc_handlers && bci >= ex_min && bci < ex_max) { verify_exception_handler_targets( bci, this_uninit, ¤t_frame, &stackmap_table, CHECK_VERIFY(this)); }