--- old/src/share/vm/interpreter/interpreterRuntime.cpp 2016-08-22 13:13:58.215666035 +0200 +++ new/src/share/vm/interpreter/interpreterRuntime.cpp 2016-08-22 13:13:58.135666038 +0200 @@ -576,10 +576,21 @@ // compute auxiliary field attributes TosState state = as_TosState(info.field_type()); - // Put instructions on final fields are not resolved. This is required so we throw - // exceptions at the correct place (when the instruction is actually invoked). + // Resolution of put instructions on final fields is delayed. That is required so that + // exceptions are thrown at the correct place (when the instruction is actually invoked). // If we do not resolve an instruction in the current pass, leaving the put_code // set to zero will cause the next put instruction to the same field to reresolve. + + // Resolution of put instructions to final instance fields with invalid updates (i.e., + // to final instance fields with updates originating from a method different than ) + // is inhibited. A putfield instruction targeting an instance final field must throw + // an IllegalAccessError if the instruction is not in an instance + // initializer method . If resolution were not inhibited, a putfield + // in an initializer method could be resolved in the initializer. Subsequent + // putfield instructions to the same field would then use cached information. + // As a result, those instructions would not pass through the VM. That is, + // checks in resolve_field_access() would not be executed for those instructions + // and the required IllegalAccessError would not not be thrown. // // Also, we need to delay resolving getstatic and putstatic instructions until the // class is initialized. This is required so that access to the static @@ -590,8 +601,17 @@ !klass->is_initialized()); Bytecodes::Code put_code = (Bytecodes::Code)0; - if (is_put && !info.access_flags().is_final() && !uninitialized_static) { - put_code = ((is_static) ? Bytecodes::_putstatic : Bytecodes::_putfield); + bool has_initialized_final_update = info.field_holder()->major_version() >= 53 && + info.has_initialized_final_update(); + + if (has_initialized_final_update) { + assert(info.access_flags().is_final(), "Fields with initialized final updates must be final"); + } + + if (!uninitialized_static) { + if ((is_put && !has_initialized_final_update) || !info.access_flags().is_final()) { + put_code = ((is_static) ? Bytecodes::_putstatic : Bytecodes::_putfield); + } } Bytecodes::Code get_code = (Bytecodes::Code)0;