< prev index next >

src/hotspot/share/oops/instanceKlass.cpp

Print this page




 133   if (class_name == vmSymbols::java_lang_ClassLoader()) {
 134     return true;
 135   }
 136 
 137   if (SystemDictionary::ClassLoader_klass_loaded()) {
 138     const Klass* const super_klass = parser.super_klass();
 139     if (super_klass != NULL) {
 140       if (super_klass->is_subtype_of(SystemDictionary::ClassLoader_klass())) {
 141         return true;
 142       }
 143     }
 144   }
 145   return false;
 146 }
 147 
 148 // called to verify that k is a member of this nest
 149 bool InstanceKlass::has_nest_member(InstanceKlass* k, TRAPS) const {
 150   if (_nest_members == NULL || _nest_members == Universe::the_empty_short_array()) {
 151     if (log_is_enabled(Trace, class, nestmates)) {
 152       ResourceMark rm(THREAD);
 153       log_trace(class, nestmates)("Checking nest membership of %s in non-nest-host class %s",
 154                                   k->name()->as_C_string(), this->name()->as_C_string());
 155     }
 156     return false;
 157   }
 158 
 159   if (log_is_enabled(Trace, class, nestmates)) {
 160     ResourceMark rm(THREAD);
 161     log_trace(class, nestmates)("Checking nest membership of %s in %s",
 162                                 k->name()->as_C_string(), this->name()->as_C_string());
 163   }
 164 
 165   // Check names first and if they match then check actual klass. This avoids
 166   // resolving anything unnecessarily.
 167   for (int i = 0; i < _nest_members->length(); i++) {
 168     int cp_index = _nest_members->at(i);
 169     Symbol* name = _constants->klass_name_at(cp_index);
 170     if (name == k->name()) {
 171       log_trace(class, nestmates)("- Found it at nest_members[%d] => cp[%d]", i, cp_index);
 172 
 173       // names match so check actual klass - this may trigger class loading if
 174       // it doesn't match (but that should be impossible)
 175       Klass* k2 = _constants->klass_at(cp_index, CHECK_false);
 176       if (k2 == k) {
 177         log_trace(class, nestmates)("- klass is nestmate member");
 178         return true;
 179       }
 180       else {
 181         // same name but different klass!
 182         log_trace(class, nestmates)(" - klass comparison failed!");
 183       }
 184     }
 185   }
 186   log_trace(class, nestmates)("- klass is NOT nestmate member!");
 187   return false;
 188 }
 189 
 190 // Return nest-host class, resolving, validating and saving it if needed




 191 InstanceKlass* InstanceKlass::nest_host(TRAPS) {
 192   InstanceKlass* nest_host_k = _nest_host;
 193   if (nest_host_k == NULL) {
 194     // need to resolve and save our nest-host class. This could be attempted
 195     // concurrently but as the result is idempotent and we don't use the class
 196     // then we do not need any synchronization beyond what is implicitly used
 197     // during class loading.
 198     if (_nest_host_index != 0) { // we have a real nest_host


 199       if (log_is_enabled(Trace, class, nestmates)) {
 200         ResourceMark rm(THREAD);
 201         log_trace(class, nestmates)("Resolving nest-host of %s using cp entry for %s",
 202                                     this->name()->as_C_string(),
 203                                     _constants->klass_name_at(_nest_host_index)->as_C_string());

 204       }
 205 
 206       Klass* k = _constants->klass_at(_nest_host_index, CHECK_NULL);
 207 
 208       if (log_is_enabled(Trace, class, nestmates)) {
 209         ResourceMark rm(THREAD);
 210         log_trace(class, nestmates)("Resolved nest-host of %s to %s",
 211                                     this->name()->as_C_string(), k->name()->as_C_string());

 212       }
 213 
 214       if (!k->is_instance_klass()) {
 215         ResourceMark rm(THREAD);
 216         Exceptions::fthrow(
 217                            THREAD_AND_LOCATION,
 218                            vmSymbols::java_lang_IncompatibleClassChangeError(),
 219                            "class %s has non-instance class %s as nest-host",
 220                            this->external_name(),
 221                            k->external_name()
 222                            );






 223         return NULL;
 224       }
 225 








 226       nest_host_k = InstanceKlass::cast(k);
 227 

 228       bool is_member = nest_host_k->has_nest_member(this, CHECK_NULL);
 229       if (!is_member) {
 230         // this_k and nest_host disagree about nest membership






 231         ResourceMark rm(THREAD);
 232         Exceptions::fthrow(
 233                            THREAD_AND_LOCATION,
 234                            vmSymbols::java_lang_IncompatibleClassChangeError(),
 235                            "Type %s is not a nest member of %s",
















 236                            this->external_name(),
 237                            nest_host_k->external_name()
 238                            );
 239         return NULL;
 240       }
 241 
 242       if (!is_same_class_package(nest_host_k)) {
 243         ResourceMark rm(THREAD);
 244         Exceptions::fthrow(
 245                            THREAD_AND_LOCATION,
 246                            vmSymbols::java_lang_IncompatibleClassChangeError(),
 247                            "Class %s is in a different package to its nest-host class %s",
 248                            this->external_name(),
 249                            nest_host_k->external_name()

 250                            );
 251         return NULL;
 252       }
 253     }
 254     else {
 255       if (log_is_enabled(Trace, class, nestmates)) {
 256         ResourceMark rm(THREAD);
 257         log_trace(class, nestmates)("Class %s is not part of a nest: setting nest-host to self",
 258                                     this->name()->as_C_string());
 259       }
 260       nest_host_k = const_cast<InstanceKlass*>(this);

 261     }
 262   }
 263   // save resolved nest-host value
 264   _nest_host = nest_host_k;
 265 
 266   return nest_host_k;
 267 }
 268 
 269 // check if 'this' and k are nestmates (same nest_host), or k is our nest_host,
 270 // or we are k's nest_host - all of which is covered by comparing the two
 271 // resolved_nest_hosts
 272 bool InstanceKlass::has_nestmate_access_to(InstanceKlass* k, TRAPS) {
 273 
 274   // If not actually nestmates, then both nest-host classes may have to loaded
 275   // and the nest membership of each class validated.
 276   InstanceKlass* cur_top = nest_host(CHECK_false);
 277   Klass* k_nest_host = k->nest_host(CHECK_false);












 278 
 279   bool access = (cur_top == k_nest_host);
 280 
 281   if (log_is_enabled(Trace, class, nestmates)) {
 282     ResourceMark rm(THREAD);
 283     log_trace(class, nestmates)("Class %s does %shave nestmate accesss to %s",
 284                                 this->name()->as_C_string(),
 285                                 access ? "" : "NOT ",
 286                                 k->name()->as_C_string());
 287   }
 288 
 289   return access;
 290 }
 291 
 292 InstanceKlass* InstanceKlass::allocate_instance_klass(const ClassFileParser& parser, TRAPS) {
 293   const int size = InstanceKlass::size(parser.vtable_size(),
 294                                        parser.itable_size(),
 295                                        nonstatic_oop_map_size(parser.total_oop_map_count()),
 296                                        parser.is_interface(),
 297                                        parser.is_anonymous(),
 298                                        should_store_fingerprint());
 299 
 300   const Symbol* const class_name = parser.class_name();
 301   assert(class_name != NULL, "invariant");
 302   ClassLoaderData* loader_data = parser.loader_data();
 303   assert(loader_data != NULL, "invariant");
 304 
 305   InstanceKlass* ik;
 306 




 133   if (class_name == vmSymbols::java_lang_ClassLoader()) {
 134     return true;
 135   }
 136 
 137   if (SystemDictionary::ClassLoader_klass_loaded()) {
 138     const Klass* const super_klass = parser.super_klass();
 139     if (super_klass != NULL) {
 140       if (super_klass->is_subtype_of(SystemDictionary::ClassLoader_klass())) {
 141         return true;
 142       }
 143     }
 144   }
 145   return false;
 146 }
 147 
 148 // called to verify that k is a member of this nest
 149 bool InstanceKlass::has_nest_member(InstanceKlass* k, TRAPS) const {
 150   if (_nest_members == NULL || _nest_members == Universe::the_empty_short_array()) {
 151     if (log_is_enabled(Trace, class, nestmates)) {
 152       ResourceMark rm(THREAD);
 153       log_trace(class, nestmates)("Checked nest membership of %s in non-nest-host class %s",
 154                                   k->external_name(), this->external_name());
 155     }
 156     return false;
 157   }
 158 
 159   if (log_is_enabled(Trace, class, nestmates)) {
 160     ResourceMark rm(THREAD);
 161     log_trace(class, nestmates)("Checking nest membership of %s in %s",
 162                                 k->external_name(), this->external_name());
 163   }
 164 
 165   // Check names first and if they match then check actual klass. This avoids
 166   // resolving anything unnecessarily.
 167   for (int i = 0; i < _nest_members->length(); i++) {
 168     int cp_index = _nest_members->at(i);
 169     Symbol* name = _constants->klass_name_at(cp_index);
 170     if (name == k->name()) {
 171       log_trace(class, nestmates)("- Found it at nest_members[%d] => cp[%d]", i, cp_index);
 172 
 173       // names match so check actual klass - this may trigger class loading if
 174       // it doesn't match (but that should be impossible)
 175       Klass* k2 = _constants->klass_at(cp_index, CHECK_false);
 176       if (k2 == k) {
 177         log_trace(class, nestmates)("- class is listed as a nest member");
 178         return true;
 179       }
 180       else {
 181         // same name but different klass!
 182         log_trace(class, nestmates)(" - klass comparison failed!");
 183       }
 184     }
 185   }
 186   log_trace(class, nestmates)("- class is NOT a nest member!");
 187   return false;
 188 }
 189 
 190 // Return nest-host class, resolving, validating and saving it if needed.
 191 // In cases where this is called from a thread that can not do classloading
 192 // (such as a native JIT thread) then we simply return NULL, which in turn
 193 // causes the access check to return false. Such code will retry the access
 194 // from a more suitable environment later.
 195 InstanceKlass* InstanceKlass::nest_host(TRAPS) {
 196   InstanceKlass* nest_host_k = _nest_host;
 197   if (nest_host_k == NULL) {
 198     // need to resolve and save our nest-host class. This could be attempted
 199     // concurrently but as the result is idempotent and we don't use the class
 200     // then we do not need any synchronization beyond what is implicitly used
 201     // during class loading.
 202     if (_nest_host_index != 0) { // we have a real nest_host
 203       // Before trying to resolve check if we're in a suitable context
 204       if (!THREAD->can_call_java() && !_constants->tag_at(_nest_host_index).is_klass()) {
 205         if (log_is_enabled(Trace, class, nestmates)) {
 206           ResourceMark rm(THREAD);
 207           log_trace(class, nestmates)("Rejected resolution of nest-host of %s in unsuitable thread",
 208                                       this->external_name());
 209         }
 210         return NULL;
 211       }


 212 
 213       if (log_is_enabled(Trace, class, nestmates)) {
 214         ResourceMark rm(THREAD);
 215         log_trace(class, nestmates)("Resolving nest-host of %s using cp entry for %s",
 216                                     this->external_name(),
 217                                     _constants->klass_name_at(_nest_host_index)->as_C_string());
 218       }
 219 
 220       Klass* k = _constants->klass_at(_nest_host_index, THREAD);
 221       if (HAS_PENDING_EXCEPTION) {
 222         Handle exc_h = Handle(THREAD, PENDING_EXCEPTION);
 223         if (exc_h->is_a(SystemDictionary::NoClassDefFoundError_klass())) {
 224           // throw a new CDNFE with the original as its cause, and a clear msg
 225           ResourceMark rm(THREAD);
 226           char buf[200];
 227           CLEAR_PENDING_EXCEPTION;
 228           jio_snprintf(buf, sizeof(buf),
 229                        "Unable to load nest-host class of %s",
 230                        this->external_name());
 231           log_trace(class, nestmates)("%s - NoClassDefFoundError", buf);
 232           THROW_MSG_CAUSE_NULL(vmSymbols::java_lang_NoClassDefFoundError(), buf, exc_h);
 233         }
 234         // other exceptions pass through (OOME, StackOverflowError etc)
 235         return NULL;
 236       }
 237 
 238       // A valid nest-host is an instance class in the current package that lists this
 239       // class as a nest member. If any of these conditions are not met we simply throw
 240       // IllegalAccessError, with a suitable message.
 241 
 242       const char* error = NULL;
 243 
 244       // Need to check we have an instance class first
 245       if (k->is_instance_klass()) {
 246         nest_host_k = InstanceKlass::cast(k);
 247 
 248         // FIXME: an exception from this is perhaps impossible
 249         bool is_member = nest_host_k->has_nest_member(this, CHECK_NULL);
 250         if (is_member) {
 251           // Finally check we're in the same package - as there could be collusion
 252           // between untrusted types.
 253           if (is_same_class_package(nest_host_k)) {
 254             // save resolved nest-host value
 255             _nest_host = nest_host_k;
 256 
 257             if (log_is_enabled(Trace, class, nestmates)) {
 258               ResourceMark rm(THREAD);
 259               log_trace(class, nestmates)("Resolved nest-host of %s to %s",
 260                                           this->external_name(), k->external_name());
 261             }
 262             return nest_host_k;
 263           }
 264           else {
 265             error = "types are in different packages";
 266           }
 267         }
 268         else {
 269           error = "current type is not listed as a nest member";
 270         }
 271       }
 272       else {
 273         error = "nest-host is not an instance class!";
 274       }
 275 
 276       if (log_is_enabled(Trace, class, nestmates)) {
 277         ResourceMark rm(THREAD);
 278         log_trace(class, nestmates)("Type %s is not a nest member of resolved type %s: %s",
 279                                     this->external_name(),
 280                                     k->external_name(),
 281                                     error);

 282       }
 283 

 284       ResourceMark rm(THREAD);
 285       Exceptions::fthrow(THREAD_AND_LOCATION,
 286                          vmSymbols::java_lang_IllegalAccessError(),
 287                          "Type %s is not a nest member of %s: %s",

 288                          this->external_name(),
 289                          k->external_name(),
 290                          error
 291                          );
 292       return NULL;
 293     }

 294     else {
 295       if (log_is_enabled(Trace, class, nestmates)) {
 296         ResourceMark rm(THREAD);
 297         log_trace(class, nestmates)("Type %s is not part of a nest: setting nest-host to self",
 298                                     this->external_name());
 299       }
 300       // save resolved nest-host value
 301       return (_nest_host = this);
 302     }
 303   }



 304   return nest_host_k;
 305 }
 306 
 307 // check if 'this' and k are nestmates (same nest_host), or k is our nest_host,
 308 // or we are k's nest_host - all of which is covered by comparing the two
 309 // resolved_nest_hosts
 310 bool InstanceKlass::has_nestmate_access_to(InstanceKlass* k, TRAPS) {
 311 
 312   assert(this != k, "this should be handled by higher-level code");
 313 
 314   // Per the JVMS we first resolve and validate the current class, then
 315   // the target class k. Resolution exceptions will be passed on by upper
 316   // layers. IllegalAccessErrors from membership validation failures will
 317   // also be passed through.
 318 
 319   InstanceKlass* cur_host = nest_host(THREAD);
 320   if (cur_host == NULL || HAS_PENDING_EXCEPTION) {
 321     return false;
 322   }
 323 
 324   Klass* k_nest_host = k->nest_host(THREAD);
 325   if (k_nest_host == NULL || HAS_PENDING_EXCEPTION) {
 326     return false;
 327   }
 328 
 329   bool access = (cur_host == k_nest_host);
 330 
 331   if (log_is_enabled(Trace, class, nestmates)) {
 332     ResourceMark rm(THREAD);
 333     log_trace(class, nestmates)("Class %s does %shave nestmate accesss to %s",
 334                                 this->external_name(),
 335                                 access ? "" : "NOT ",
 336                                 k->external_name());
 337   }
 338 
 339   return access;
 340 }
 341 
 342 InstanceKlass* InstanceKlass::allocate_instance_klass(const ClassFileParser& parser, TRAPS) {
 343   const int size = InstanceKlass::size(parser.vtable_size(),
 344                                        parser.itable_size(),
 345                                        nonstatic_oop_map_size(parser.total_oop_map_count()),
 346                                        parser.is_interface(),
 347                                        parser.is_anonymous(),
 348                                        should_store_fingerprint());
 349 
 350   const Symbol* const class_name = parser.class_name();
 351   assert(class_name != NULL, "invariant");
 352   ClassLoaderData* loader_data = parser.loader_data();
 353   assert(loader_data != NULL, "invariant");
 354 
 355   InstanceKlass* ik;
 356 


< prev index next >