< prev index next >
src/hotspot/share/interpreter/linkResolver.cpp
Print this page
*** 943,957 ****
const LinkInfo& link_info,
Bytecodes::Code byte, bool initialize_class,
TRAPS) {
assert(byte == Bytecodes::_getstatic || byte == Bytecodes::_putstatic ||
byte == Bytecodes::_getfield || byte == Bytecodes::_putfield ||
byte == Bytecodes::_nofast_getfield || byte == Bytecodes::_nofast_putfield ||
(byte == Bytecodes::_nop && !link_info.check_access()), "bad field access bytecode");
bool is_static = (byte == Bytecodes::_getstatic || byte == Bytecodes::_putstatic);
! bool is_put = (byte == Bytecodes::_putfield || byte == Bytecodes::_putstatic || byte == Bytecodes::_nofast_putfield);
// Check if there's a resolved klass containing the field
Klass* resolved_klass = link_info.resolved_klass();
Symbol* field = link_info.name();
Symbol* sig = link_info.signature();
--- 943,959 ----
const LinkInfo& link_info,
Bytecodes::Code byte, bool initialize_class,
TRAPS) {
assert(byte == Bytecodes::_getstatic || byte == Bytecodes::_putstatic ||
byte == Bytecodes::_getfield || byte == Bytecodes::_putfield ||
+ byte == Bytecodes::_withfield ||
byte == Bytecodes::_nofast_getfield || byte == Bytecodes::_nofast_putfield ||
(byte == Bytecodes::_nop && !link_info.check_access()), "bad field access bytecode");
bool is_static = (byte == Bytecodes::_getstatic || byte == Bytecodes::_putstatic);
! bool is_put = (byte == Bytecodes::_putfield || byte == Bytecodes::_putstatic ||
! byte == Bytecodes::_nofast_putfield || byte == Bytecodes::_withfield);
// Check if there's a resolved klass containing the field
Klass* resolved_klass = link_info.resolved_klass();
Symbol* field = link_info.name();
Symbol* sig = link_info.signature();
*** 985,1004 ****
--- 987,1018 ----
// A final field can be modified only
// (1) by methods declared in the class declaring the field and
// (2) by the <clinit> method (in case of a static field)
// or by the <init> method (in case of an instance field).
+ // (3) by withfield when field is in a value type and the
+ // selected class and current class are nest mates.
if (is_put && fd.access_flags().is_final()) {
ResourceMark rm(THREAD);
stringStream ss;
if (sel_klass != current_klass) {
+ // If byte code is a withfield check if they are nestmates.
+ bool are_nestmates = false;
+ if (sel_klass->is_instance_klass() &&
+ InstanceKlass::cast(sel_klass)->is_value() &&
+ current_klass->is_instance_klass()) {
+ are_nestmates = InstanceKlass::cast(link_info.current_klass())->has_nestmate_access_to(
+ InstanceKlass::cast(sel_klass), THREAD);
+ }
+ if (!are_nestmates) {
ss.print("Update to %s final field %s.%s attempted from a different class (%s) than the field's declaring class",
is_static ? "static" : "non-static", resolved_klass->external_name(), fd.name()->as_C_string(),
current_klass->external_name());
THROW_MSG(vmSymbols::java_lang_IllegalAccessError(), ss.as_string());
}
+ }
if (fd.constants()->pool_holder()->major_version() >= 53) {
methodHandle m = link_info.current_method();
assert(!m.is_null(), "information about the current method must be available for 'put' bytecodes");
bool is_initialized_static_final_update = (byte == Bytecodes::_putstatic &&
< prev index next >