src/hotspot/share/interpreter/linkResolver.cpp
changeset 52162 279174cb3a24
parent 52066 49a21be61dcd
child 52823 f5d0926026ec
equal deleted inserted replaced
52161:f1b6c4079be0 52162:279174cb3a24
   972   if (sel_klass == NULL) {
   972   if (sel_klass == NULL) {
   973     ResourceMark rm(THREAD);
   973     ResourceMark rm(THREAD);
   974     THROW_MSG(vmSymbols::java_lang_NoSuchFieldError(), field->as_C_string());
   974     THROW_MSG(vmSymbols::java_lang_NoSuchFieldError(), field->as_C_string());
   975   }
   975   }
   976 
   976 
   977   if (!link_info.check_access())
   977   // Access checking may be turned off when calling from within the VM.
   978     // Access checking may be turned off when calling from within the VM.
       
   979     return;
       
   980 
       
   981   // check access
       
   982   Klass* current_klass = link_info.current_klass();
   978   Klass* current_klass = link_info.current_klass();
   983   check_field_accessability(current_klass, resolved_klass, sel_klass, fd, CHECK);
   979   if (link_info.check_access()) {
   984 
   980 
   985   // check for errors
   981     // check access
   986   if (is_static != fd.is_static()) {
   982     check_field_accessability(current_klass, resolved_klass, sel_klass, fd, CHECK);
   987     ResourceMark rm(THREAD);
   983 
   988     char msg[200];
   984     // check for errors
   989     jio_snprintf(msg, sizeof(msg), "Expected %s field %s.%s", is_static ? "static" : "non-static", resolved_klass->external_name(), fd.name()->as_C_string());
   985     if (is_static != fd.is_static()) {
   990     THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), msg);
   986       ResourceMark rm(THREAD);
   991   }
   987       char msg[200];
   992 
   988       jio_snprintf(msg, sizeof(msg), "Expected %s field %s.%s", is_static ? "static" : "non-static", resolved_klass->external_name(), fd.name()->as_C_string());
   993   // A final field can be modified only
   989       THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), msg);
   994   // (1) by methods declared in the class declaring the field and
   990     }
   995   // (2) by the <clinit> method (in case of a static field)
   991 
   996   //     or by the <init> method (in case of an instance field).
   992     // A final field can be modified only
   997   if (is_put && fd.access_flags().is_final()) {
   993     // (1) by methods declared in the class declaring the field and
   998     ResourceMark rm(THREAD);
   994     // (2) by the <clinit> method (in case of a static field)
   999     stringStream ss;
   995     //     or by the <init> method (in case of an instance field).
  1000 
   996     if (is_put && fd.access_flags().is_final()) {
  1001     if (sel_klass != current_klass) {
   997       ResourceMark rm(THREAD);
  1002       ss.print("Update to %s final field %s.%s attempted from a different class (%s) than the field's declaring class",
   998       stringStream ss;
  1003                 is_static ? "static" : "non-static", resolved_klass->external_name(), fd.name()->as_C_string(),
   999 
       
  1000       if (sel_klass != current_klass) {
       
  1001         ss.print("Update to %s final field %s.%s attempted from a different class (%s) than the field's declaring class",
       
  1002                  is_static ? "static" : "non-static", resolved_klass->external_name(), fd.name()->as_C_string(),
  1004                 current_klass->external_name());
  1003                 current_klass->external_name());
  1005       THROW_MSG(vmSymbols::java_lang_IllegalAccessError(), ss.as_string());
       
  1006     }
       
  1007 
       
  1008     if (fd.constants()->pool_holder()->major_version() >= 53) {
       
  1009       methodHandle m = link_info.current_method();
       
  1010       assert(!m.is_null(), "information about the current method must be available for 'put' bytecodes");
       
  1011       bool is_initialized_static_final_update = (byte == Bytecodes::_putstatic &&
       
  1012                                                  fd.is_static() &&
       
  1013                                                  !m()->is_static_initializer());
       
  1014       bool is_initialized_instance_final_update = ((byte == Bytecodes::_putfield || byte == Bytecodes::_nofast_putfield) &&
       
  1015                                                    !fd.is_static() &&
       
  1016                                                    !m->is_object_initializer());
       
  1017 
       
  1018       if (is_initialized_static_final_update || is_initialized_instance_final_update) {
       
  1019         ss.print("Update to %s final field %s.%s attempted from a different method (%s) than the initializer method %s ",
       
  1020                  is_static ? "static" : "non-static", resolved_klass->external_name(), fd.name()->as_C_string(),
       
  1021                  m()->name()->as_C_string(),
       
  1022                  is_static ? "<clinit>" : "<init>");
       
  1023         THROW_MSG(vmSymbols::java_lang_IllegalAccessError(), ss.as_string());
  1004         THROW_MSG(vmSymbols::java_lang_IllegalAccessError(), ss.as_string());
  1024       }
  1005       }
  1025     }
  1006 
  1026   }
  1007       if (fd.constants()->pool_holder()->major_version() >= 53) {
  1027 
  1008         methodHandle m = link_info.current_method();
  1028   // initialize resolved_klass if necessary
  1009         assert(!m.is_null(), "information about the current method must be available for 'put' bytecodes");
  1029   // note 1: the klass which declared the field must be initialized (i.e, sel_klass)
  1010         bool is_initialized_static_final_update = (byte == Bytecodes::_putstatic &&
  1030   //         according to the newest JVM spec (5.5, p.170) - was bug (gri 7/28/99)
  1011                                                    fd.is_static() &&
  1031   //
  1012                                                    !m()->is_static_initializer());
  1032   // note 2: we don't want to force initialization if we are just checking
  1013         bool is_initialized_instance_final_update = ((byte == Bytecodes::_putfield || byte == Bytecodes::_nofast_putfield) &&
  1033   //         if the field access is legal; e.g., during compilation
  1014                                                      !fd.is_static() &&
  1034   if (is_static && initialize_class) {
  1015                                                      !m->is_object_initializer());
  1035     sel_klass->initialize(CHECK);
  1016 
  1036   }
  1017         if (is_initialized_static_final_update || is_initialized_instance_final_update) {
  1037 
  1018           ss.print("Update to %s final field %s.%s attempted from a different method (%s) than the initializer method %s ",
  1038   if (sel_klass != current_klass) {
  1019                    is_static ? "static" : "non-static", resolved_klass->external_name(), fd.name()->as_C_string(),
       
  1020                    m()->name()->as_C_string(),
       
  1021                    is_static ? "<clinit>" : "<init>");
       
  1022           THROW_MSG(vmSymbols::java_lang_IllegalAccessError(), ss.as_string());
       
  1023         }
       
  1024       }
       
  1025     }
       
  1026 
       
  1027     // initialize resolved_klass if necessary
       
  1028     // note 1: the klass which declared the field must be initialized (i.e, sel_klass)
       
  1029     //         according to the newest JVM spec (5.5, p.170) - was bug (gri 7/28/99)
       
  1030     //
       
  1031     // note 2: we don't want to force initialization if we are just checking
       
  1032     //         if the field access is legal; e.g., during compilation
       
  1033     if (is_static && initialize_class) {
       
  1034       sel_klass->initialize(CHECK);
       
  1035     }
       
  1036   }
       
  1037 
       
  1038   if ((sel_klass != current_klass) && (current_klass != NULL)) {
  1039     check_field_loader_constraints(field, sig, current_klass, sel_klass, CHECK);
  1039     check_field_loader_constraints(field, sig, current_klass, sel_klass, CHECK);
  1040   }
  1040   }
  1041 
  1041 
  1042   // return information. note that the klass is set to the actual klass containing the
  1042   // return information. note that the klass is set to the actual klass containing the
  1043   // field, otherwise access of static fields in superclasses will not work.
  1043   // field, otherwise access of static fields in superclasses will not work.