< prev index next >

src/hotspot/share/interpreter/linkResolver.cpp

Print this page

        

@@ -943,15 +943,17 @@
                                  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);
+  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,20 +987,32 @@
 
     // 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 >