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. |