< prev index next >

src/hotspot/share/interpreter/linkResolver.cpp

Print this page




 914       "tried to access field %s.%s from class %s",
 915       sel_klass->external_name(),
 916       fd.name()->as_C_string(),
 917       ref_klass->external_name()
 918     );
 919     return;
 920   }
 921 }
 922 
 923 void LinkResolver::resolve_field_access(fieldDescriptor& fd, const constantPoolHandle& pool, int index, const methodHandle& method, Bytecodes::Code byte, TRAPS) {
 924   LinkInfo link_info(pool, index, method, CHECK);
 925   resolve_field(fd, link_info, byte, true, CHECK);
 926 }
 927 
 928 void LinkResolver::resolve_field(fieldDescriptor& fd,
 929                                  const LinkInfo& link_info,
 930                                  Bytecodes::Code byte, bool initialize_class,
 931                                  TRAPS) {
 932   assert(byte == Bytecodes::_getstatic || byte == Bytecodes::_putstatic ||
 933          byte == Bytecodes::_getfield  || byte == Bytecodes::_putfield  ||
 934          byte == Bytecodes::_vwithfield ||
 935          byte == Bytecodes::_nofast_getfield  || byte == Bytecodes::_nofast_putfield  ||
 936          (byte == Bytecodes::_nop && !link_info.check_access()), "bad field access bytecode");
 937 
 938   bool is_static = (byte == Bytecodes::_getstatic || byte == Bytecodes::_putstatic);
 939   bool is_put    = (byte == Bytecodes::_putfield  || byte == Bytecodes::_putstatic || byte == Bytecodes::_nofast_putfield
 940                     || byte == Bytecodes::_vwithfield);
 941   // Check if there's a resolved klass containing the field
 942   Klass* resolved_klass = link_info.resolved_klass();
 943   Symbol* field = link_info.name();
 944   Symbol* sig = link_info.signature();
 945 
 946   if (resolved_klass == NULL) {
 947     ResourceMark rm(THREAD);
 948     THROW_MSG(vmSymbols::java_lang_NoSuchFieldError(), field->as_C_string());
 949   }
 950 
 951   // Resolve instance field
 952   Klass* sel_klass = resolved_klass->find_field(field, sig, &fd);
 953   // check if field exists; i.e., if a klass containing the field def has been selected
 954   if (sel_klass == NULL) {
 955     ResourceMark rm(THREAD);
 956     THROW_MSG(vmSymbols::java_lang_NoSuchFieldError(), field->as_C_string());
 957   }
 958 
 959   if (!link_info.check_access())
 960     // Access checking may be turned off when calling from within the VM.


 964   Klass* current_klass = link_info.current_klass();
 965   check_field_accessability(current_klass, resolved_klass, sel_klass, fd, CHECK);
 966 
 967   // check for errors
 968   if (is_static != fd.is_static()) {
 969     ResourceMark rm(THREAD);
 970     char msg[200];
 971     jio_snprintf(msg, sizeof(msg), "Expected %s field %s.%s", is_static ? "static" : "non-static", resolved_klass->external_name(), fd.name()->as_C_string());
 972     THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), msg);
 973   }
 974 
 975   // A final field can be modified only
 976   // (1) by methods declared in the class declaring the field and
 977   // (2) by the <clinit> method (in case of a static field)
 978   //     or by the <init> method (in case of an instance field).
 979   if (is_put && fd.access_flags().is_final()) {
 980     ResourceMark rm(THREAD);
 981     stringStream ss;
 982 
 983     if (sel_klass != current_klass) {
 984       // For Minimal Value Types check if the current class is an anonymous
 985       // class whose host class is the Derived Value Type class (selected class)
 986       // or the Value Capable Class (VCC)
 987       if (byte == Bytecodes::_vwithfield) {
 988         assert(sel_klass->is_value(), "Expected Value Type");
 989         if (current_klass->is_instance_klass() && InstanceKlass::cast(current_klass)->is_anonymous()) {
 990           Klass* host_klass = InstanceKlass::cast(current_klass)->host_klass(); // Is host VCC of DVT ?
 991 
 992           if (sel_klass == host_klass  || // Is DVT
 993               (host_klass->is_instance_klass() && // Is VCC
 994                InstanceKlass::cast(sel_klass)->get_vcc_klass() == host_klass)) {
 995             return;
 996           }
 997         }
 998       }
 999 
1000       ss.print("Update to %s final field %s.%s attempted from a different class (%s) than the field's declaring class",
1001                 is_static ? "static" : "non-static", resolved_klass->external_name(), fd.name()->as_C_string(),
1002                 current_klass->external_name());
1003       THROW_MSG(vmSymbols::java_lang_IllegalAccessError(), ss.as_string());
1004     }
1005 
1006     if (fd.constants()->pool_holder()->major_version() >= 53) {
1007       methodHandle m = link_info.current_method();
1008       assert(!m.is_null(), "information about the current method must be available for 'put' bytecodes");
1009       bool is_initialized_static_final_update = (byte == Bytecodes::_putstatic &&
1010                                                  fd.is_static() &&
1011                                                  !m()->is_static_initializer());
1012       bool is_initialized_instance_final_update = ((byte == Bytecodes::_putfield || byte == Bytecodes::_nofast_putfield) &&
1013                                                    !fd.is_static() &&
1014                                                    !m->is_object_initializer());
1015 
1016       if (is_initialized_static_final_update || is_initialized_instance_final_update) {
1017         ss.print("Update to %s final field %s.%s attempted from a different method (%s) than the initializer method %s ",
1018                  is_static ? "static" : "non-static", resolved_klass->external_name(), fd.name()->as_C_string(),
1019                  m()->name()->as_C_string(),




 914       "tried to access field %s.%s from class %s",
 915       sel_klass->external_name(),
 916       fd.name()->as_C_string(),
 917       ref_klass->external_name()
 918     );
 919     return;
 920   }
 921 }
 922 
 923 void LinkResolver::resolve_field_access(fieldDescriptor& fd, const constantPoolHandle& pool, int index, const methodHandle& method, Bytecodes::Code byte, TRAPS) {
 924   LinkInfo link_info(pool, index, method, CHECK);
 925   resolve_field(fd, link_info, byte, true, CHECK);
 926 }
 927 
 928 void LinkResolver::resolve_field(fieldDescriptor& fd,
 929                                  const LinkInfo& link_info,
 930                                  Bytecodes::Code byte, bool initialize_class,
 931                                  TRAPS) {
 932   assert(byte == Bytecodes::_getstatic || byte == Bytecodes::_putstatic ||
 933          byte == Bytecodes::_getfield  || byte == Bytecodes::_putfield  ||
 934          byte == Bytecodes::_withfield ||
 935          byte == Bytecodes::_nofast_getfield  || byte == Bytecodes::_nofast_putfield  ||
 936          (byte == Bytecodes::_nop && !link_info.check_access()), "bad field access bytecode");
 937 
 938   bool is_static = (byte == Bytecodes::_getstatic || byte == Bytecodes::_putstatic);
 939   bool is_put    = (byte == Bytecodes::_putfield  || byte == Bytecodes::_putstatic || byte == Bytecodes::_nofast_putfield
 940                     || byte == Bytecodes::_withfield);
 941   // Check if there's a resolved klass containing the field
 942   Klass* resolved_klass = link_info.resolved_klass();
 943   Symbol* field = link_info.name();
 944   Symbol* sig = link_info.signature();
 945 
 946   if (resolved_klass == NULL) {
 947     ResourceMark rm(THREAD);
 948     THROW_MSG(vmSymbols::java_lang_NoSuchFieldError(), field->as_C_string());
 949   }
 950 
 951   // Resolve instance field
 952   Klass* sel_klass = resolved_klass->find_field(field, sig, &fd);
 953   // check if field exists; i.e., if a klass containing the field def has been selected
 954   if (sel_klass == NULL) {
 955     ResourceMark rm(THREAD);
 956     THROW_MSG(vmSymbols::java_lang_NoSuchFieldError(), field->as_C_string());
 957   }
 958 
 959   if (!link_info.check_access())
 960     // Access checking may be turned off when calling from within the VM.


 964   Klass* current_klass = link_info.current_klass();
 965   check_field_accessability(current_klass, resolved_klass, sel_klass, fd, CHECK);
 966 
 967   // check for errors
 968   if (is_static != fd.is_static()) {
 969     ResourceMark rm(THREAD);
 970     char msg[200];
 971     jio_snprintf(msg, sizeof(msg), "Expected %s field %s.%s", is_static ? "static" : "non-static", resolved_klass->external_name(), fd.name()->as_C_string());
 972     THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), msg);
 973   }
 974 
 975   // A final field can be modified only
 976   // (1) by methods declared in the class declaring the field and
 977   // (2) by the <clinit> method (in case of a static field)
 978   //     or by the <init> method (in case of an instance field).
 979   if (is_put && fd.access_flags().is_final()) {
 980     ResourceMark rm(THREAD);
 981     stringStream ss;
 982 
 983     if (sel_klass != current_klass) {
















 984       ss.print("Update to %s final field %s.%s attempted from a different class (%s) than the field's declaring class",
 985                 is_static ? "static" : "non-static", resolved_klass->external_name(), fd.name()->as_C_string(),
 986                 current_klass->external_name());
 987       THROW_MSG(vmSymbols::java_lang_IllegalAccessError(), ss.as_string());
 988     }
 989 
 990     if (fd.constants()->pool_holder()->major_version() >= 53) {
 991       methodHandle m = link_info.current_method();
 992       assert(!m.is_null(), "information about the current method must be available for 'put' bytecodes");
 993       bool is_initialized_static_final_update = (byte == Bytecodes::_putstatic &&
 994                                                  fd.is_static() &&
 995                                                  !m()->is_static_initializer());
 996       bool is_initialized_instance_final_update = ((byte == Bytecodes::_putfield || byte == Bytecodes::_nofast_putfield) &&
 997                                                    !fd.is_static() &&
 998                                                    !m->is_object_initializer());
 999 
1000       if (is_initialized_static_final_update || is_initialized_instance_final_update) {
1001         ss.print("Update to %s final field %s.%s attempted from a different method (%s) than the initializer method %s ",
1002                  is_static ? "static" : "non-static", resolved_klass->external_name(), fd.name()->as_C_string(),
1003                  m()->name()->as_C_string(),


< prev index next >