< prev index next >

src/hotspot/share/interpreter/linkResolver.cpp

Print this page




 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       }


< prev index next >