928 fd.name()->as_C_string(),
929 (same_module) ? ref_klass->joint_in_module_of_loader(sel_klass) : ref_klass->class_in_module_of_loader(),
930 (same_module) ? "" : "; ",
931 (same_module) ? "" : sel_klass->class_in_module_of_loader()
932 );
933 return;
934 }
935 }
936
937 void LinkResolver::resolve_field_access(fieldDescriptor& fd, const constantPoolHandle& pool, int index, const methodHandle& method, Bytecodes::Code byte, TRAPS) {
938 LinkInfo link_info(pool, index, method, CHECK);
939 resolve_field(fd, link_info, byte, true, CHECK);
940 }
941
942 void LinkResolver::resolve_field(fieldDescriptor& fd,
943 const LinkInfo& link_info,
944 Bytecodes::Code byte, bool initialize_class,
945 TRAPS) {
946 assert(byte == Bytecodes::_getstatic || byte == Bytecodes::_putstatic ||
947 byte == Bytecodes::_getfield || byte == Bytecodes::_putfield ||
948 byte == Bytecodes::_nofast_getfield || byte == Bytecodes::_nofast_putfield ||
949 (byte == Bytecodes::_nop && !link_info.check_access()), "bad field access bytecode");
950
951 bool is_static = (byte == Bytecodes::_getstatic || byte == Bytecodes::_putstatic);
952 bool is_put = (byte == Bytecodes::_putfield || byte == Bytecodes::_putstatic || byte == Bytecodes::_nofast_putfield);
953 // Check if there's a resolved klass containing the field
954 Klass* resolved_klass = link_info.resolved_klass();
955 Symbol* field = link_info.name();
956 Symbol* sig = link_info.signature();
957
958 if (resolved_klass == NULL) {
959 ResourceMark rm(THREAD);
960 THROW_MSG(vmSymbols::java_lang_NoSuchFieldError(), field->as_C_string());
961 }
962
963 // Resolve instance field
964 Klass* sel_klass = resolved_klass->find_field(field, sig, &fd);
965 // check if field exists; i.e., if a klass containing the field def has been selected
966 if (sel_klass == NULL) {
967 ResourceMark rm(THREAD);
968 THROW_MSG(vmSymbols::java_lang_NoSuchFieldError(), field->as_C_string());
969 }
970
971 // Access checking may be turned off when calling from within the VM.
972 Klass* current_klass = link_info.current_klass();
973 if (link_info.check_access()) {
974
975 // check access
976 check_field_accessability(current_klass, resolved_klass, sel_klass, fd, CHECK);
977
978 // check for errors
979 if (is_static != fd.is_static()) {
980 ResourceMark rm(THREAD);
981 char msg[200];
982 jio_snprintf(msg, sizeof(msg), "Expected %s field %s.%s", is_static ? "static" : "non-static", resolved_klass->external_name(), fd.name()->as_C_string());
983 THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), msg);
984 }
985
986 // A final field can be modified only
987 // (1) by methods declared in the class declaring the field and
988 // (2) by the <clinit> method (in case of a static field)
989 // or by the <init> method (in case of an instance field).
990 if (is_put && fd.access_flags().is_final()) {
991 ResourceMark rm(THREAD);
992 stringStream ss;
993
994 if (sel_klass != current_klass) {
995 ss.print("Update to %s final field %s.%s attempted from a different class (%s) than the field's declaring class",
996 is_static ? "static" : "non-static", resolved_klass->external_name(), fd.name()->as_C_string(),
997 current_klass->external_name());
998 THROW_MSG(vmSymbols::java_lang_IllegalAccessError(), ss.as_string());
999 }
1000
1001 if (fd.constants()->pool_holder()->major_version() >= 53) {
1002 methodHandle m = link_info.current_method();
1003 assert(!m.is_null(), "information about the current method must be available for 'put' bytecodes");
1004 bool is_initialized_static_final_update = (byte == Bytecodes::_putstatic &&
1005 fd.is_static() &&
1006 !m()->is_static_initializer());
1007 bool is_initialized_instance_final_update = ((byte == Bytecodes::_putfield || byte == Bytecodes::_nofast_putfield) &&
1008 !fd.is_static() &&
1009 !m->is_object_initializer());
1010
1011 if (is_initialized_static_final_update || is_initialized_instance_final_update) {
1012 ss.print("Update to %s final field %s.%s attempted from a different method (%s) than the initializer method %s ",
1013 is_static ? "static" : "non-static", resolved_klass->external_name(), fd.name()->as_C_string(),
1014 m()->name()->as_C_string(),
1015 is_static ? "<clinit>" : "<init>");
1016 THROW_MSG(vmSymbols::java_lang_IllegalAccessError(), ss.as_string());
1017 }
1018 }
|
928 fd.name()->as_C_string(),
929 (same_module) ? ref_klass->joint_in_module_of_loader(sel_klass) : ref_klass->class_in_module_of_loader(),
930 (same_module) ? "" : "; ",
931 (same_module) ? "" : sel_klass->class_in_module_of_loader()
932 );
933 return;
934 }
935 }
936
937 void LinkResolver::resolve_field_access(fieldDescriptor& fd, const constantPoolHandle& pool, int index, const methodHandle& method, Bytecodes::Code byte, TRAPS) {
938 LinkInfo link_info(pool, index, method, CHECK);
939 resolve_field(fd, link_info, byte, true, CHECK);
940 }
941
942 void LinkResolver::resolve_field(fieldDescriptor& fd,
943 const LinkInfo& link_info,
944 Bytecodes::Code byte, bool initialize_class,
945 TRAPS) {
946 assert(byte == Bytecodes::_getstatic || byte == Bytecodes::_putstatic ||
947 byte == Bytecodes::_getfield || byte == Bytecodes::_putfield ||
948 byte == Bytecodes::_withfield ||
949 byte == Bytecodes::_nofast_getfield || byte == Bytecodes::_nofast_putfield ||
950 (byte == Bytecodes::_nop && !link_info.check_access()), "bad field access bytecode");
951
952 bool is_static = (byte == Bytecodes::_getstatic || byte == Bytecodes::_putstatic);
953 bool is_put = (byte == Bytecodes::_putfield || byte == Bytecodes::_putstatic ||
954 byte == Bytecodes::_nofast_putfield || byte == Bytecodes::_withfield);
955 // Check if there's a resolved klass containing the field
956 Klass* resolved_klass = link_info.resolved_klass();
957 Symbol* field = link_info.name();
958 Symbol* sig = link_info.signature();
959
960 if (resolved_klass == NULL) {
961 ResourceMark rm(THREAD);
962 THROW_MSG(vmSymbols::java_lang_NoSuchFieldError(), field->as_C_string());
963 }
964
965 // Resolve instance field
966 Klass* sel_klass = resolved_klass->find_field(field, sig, &fd);
967 // check if field exists; i.e., if a klass containing the field def has been selected
968 if (sel_klass == NULL) {
969 ResourceMark rm(THREAD);
970 THROW_MSG(vmSymbols::java_lang_NoSuchFieldError(), field->as_C_string());
971 }
972
973 // Access checking may be turned off when calling from within the VM.
974 Klass* current_klass = link_info.current_klass();
975 if (link_info.check_access()) {
976
977 // check access
978 check_field_accessability(current_klass, resolved_klass, sel_klass, fd, CHECK);
979
980 // check for errors
981 if (is_static != fd.is_static()) {
982 ResourceMark rm(THREAD);
983 char msg[200];
984 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 THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), msg);
986 }
987
988 // A final field can be modified only
989 // (1) by methods declared in the class declaring the field and
990 // (2) by the <clinit> method (in case of a static field)
991 // or by the <init> method (in case of an instance field).
992 // (3) by withfield when field is in a value type and the
993 // selected class and current class are nest mates.
994 if (is_put && fd.access_flags().is_final()) {
995 ResourceMark rm(THREAD);
996 stringStream ss;
997
998 if (sel_klass != current_klass) {
999 // If byte code is a withfield check if they are nestmates.
1000 bool are_nestmates = false;
1001 if (sel_klass->is_instance_klass() &&
1002 InstanceKlass::cast(sel_klass)->is_value() &&
1003 current_klass->is_instance_klass()) {
1004 are_nestmates = InstanceKlass::cast(link_info.current_klass())->has_nestmate_access_to(
1005 InstanceKlass::cast(sel_klass), THREAD);
1006 }
1007 if (!are_nestmates) {
1008 ss.print("Update to %s final field %s.%s attempted from a different class (%s) than the field's declaring class",
1009 is_static ? "static" : "non-static", resolved_klass->external_name(), fd.name()->as_C_string(),
1010 current_klass->external_name());
1011 THROW_MSG(vmSymbols::java_lang_IllegalAccessError(), ss.as_string());
1012 }
1013 }
1014
1015 if (fd.constants()->pool_holder()->major_version() >= 53) {
1016 methodHandle m = link_info.current_method();
1017 assert(!m.is_null(), "information about the current method must be available for 'put' bytecodes");
1018 bool is_initialized_static_final_update = (byte == Bytecodes::_putstatic &&
1019 fd.is_static() &&
1020 !m()->is_static_initializer());
1021 bool is_initialized_instance_final_update = ((byte == Bytecodes::_putfield || byte == Bytecodes::_nofast_putfield) &&
1022 !fd.is_static() &&
1023 !m->is_object_initializer());
1024
1025 if (is_initialized_static_final_update || is_initialized_instance_final_update) {
1026 ss.print("Update to %s final field %s.%s attempted from a different method (%s) than the initializer method %s ",
1027 is_static ? "static" : "non-static", resolved_klass->external_name(), fd.name()->as_C_string(),
1028 m()->name()->as_C_string(),
1029 is_static ? "<clinit>" : "<init>");
1030 THROW_MSG(vmSymbols::java_lang_IllegalAccessError(), ss.as_string());
1031 }
1032 }
|