< prev index next >

src/hotspot/share/oops/instanceKlass.cpp

Print this page

        

@@ -209,10 +209,64 @@
   }
   log_trace(class, nestmates)("- class is NOT a nest member!");
   return false;
 }
 
+// Called to verify that k is a permitted subtype of this class
+bool InstanceKlass::has_as_permitted_subtype(InstanceKlass* k, TRAPS) const {
+  if (k == NULL) {
+    if (log_is_enabled(Trace, class, sealed)) {
+      ResourceMark rm(THREAD);
+      log_trace(class, sealed)("Checked for permitted subtype of %s with a NULL instance class", this->external_name());
+    }
+    return false;
+  }
+  if (_permitted_subtypes == NULL || _permitted_subtypes == Universe::the_empty_short_array()) {
+    if (log_is_enabled(Trace, class, sealed)) {
+      ResourceMark rm(THREAD);
+      log_trace(class, sealed)("Checked for permitted subtype of %s in non-sealed class %s",
+                                  k->external_name(), this->external_name());
+    }
+    return false;
+  }
+
+  if (log_is_enabled(Trace, class, sealed)) {
+    ResourceMark rm(THREAD);
+    log_trace(class, sealed)("Checking for permitted subtype of %s in %s",
+                                k->external_name(), this->external_name());
+  }
+
+  oop classloader1 = this->class_loader();
+  oop classloader2 = k->class_loader();
+  if (!oopDesc::equals(classloader1, classloader2)) {
+      log_trace(class, sealed)("Checked for same class loader of permitted subtype of %s and sealed class %s",
+                                        k->external_name(), this->external_name());
+      return false;
+  }
+
+  // Check for a resolved cp entry, else fall back to a name check.
+  // We don't want to resolve any class other than the one being checked.
+  for (int i = 0; i < _permitted_subtypes->length(); i++) {
+    int cp_index = _permitted_subtypes->at(i);
+    if (_constants->tag_at(cp_index).is_klass()) {
+      Klass* k2 = _constants->klass_at(cp_index, CHECK_false);
+      if (k2 == k) {
+        log_trace(class, sealed)("- class is listed at permitted_subtypes[%d] => cp[%d]", i, cp_index);
+        return true;
+      }
+    } else {
+      Symbol* name = _constants->klass_name_at(cp_index);
+      if (name == k->name()) {
+        log_trace(class, sealed)("- Found it at permitted_subtypes[%d] => cp[%d]", i, cp_index);
+        return true;
+      }
+    }
+  }
+  log_trace(class, sealed)("- class is NOT a permitted subtype!");
+  return false;
+}
+
 // Return nest-host class, resolving, validating and saving it if needed.
 // In cases where this is called from a thread that can not do classloading
 // (such as a native JIT thread) then we simply return NULL, which in turn
 // causes the access check to return false. Such code will retry the access
 // from a more suitable environment later.

@@ -433,10 +487,11 @@
 InstanceKlass::InstanceKlass(const ClassFileParser& parser, unsigned kind, KlassID id) :
   Klass(id),
   _nest_members(NULL),
   _nest_host_index(0),
   _nest_host(NULL),
+  _permitted_subtypes(NULL),
   _static_field_size(parser.static_field_size()),
   _nonstatic_oop_map_size(nonstatic_oop_map_size(parser.total_oop_map_count())),
   _itable_len(parser.itable_size()),
   _init_thread(NULL),
   _init_state(allocated),

@@ -595,10 +650,23 @@
       !nest_members()->is_shared()) {
     MetadataFactory::free_array<jushort>(loader_data, nest_members());
   }
   set_nest_members(NULL);
 
+  if (record_params() != NULL &&
+      record_params() != Universe::the_empty_short_array()) {
+    MetadataFactory::free_array<jushort>(loader_data, record_params());
+  }
+  set_record_params(NULL, 0);
+
+  if (permitted_subtypes() != NULL &&
+      permitted_subtypes() != Universe::the_empty_short_array() &&
+      !permitted_subtypes()->is_shared()) {
+    MetadataFactory::free_array<jushort>(loader_data, permitted_subtypes());
+  }
+  set_permitted_subtypes(NULL);
+
   // We should deallocate the Annotations instance if it's not in shared spaces.
   if (annotations() != NULL && !annotations()->is_shared()) {
     MetadataFactory::free_metadata(loader_data, annotations());
   }
   set_annotations(NULL);

@@ -606,10 +674,17 @@
   if (DumpSharedSpaces || DynamicDumpSharedSpaces) {
     SystemDictionaryShared::remove_dumptime_info(this);
   }
 }
 
+bool InstanceKlass::is_sealed() const {
+  return is_final() &&
+        _permitted_subtypes != NULL &&
+        _permitted_subtypes != Universe::the_empty_short_array() &&
+        _permitted_subtypes->length() > 0;
+}
+
 bool InstanceKlass::should_be_initialized() const {
   return !is_initialized();
 }
 
 klassItable InstanceKlass::itable() const {

@@ -2311,10 +2386,12 @@
       }
     }
   }
 
   it->push(&_nest_members);
+  it->push(&_record_params);
+  it->push(&_permitted_subtypes);
 }
 
 void InstanceKlass::remove_unshareable_info() {
   Klass::remove_unshareable_info();
 

@@ -3226,10 +3303,11 @@
     generic_signature()->print_value_on(st);
     st->cr();
   }
   st->print(BULLET"inner classes:     "); inner_classes()->print_value_on(st);     st->cr();
   st->print(BULLET"nest members:     "); nest_members()->print_value_on(st);     st->cr();
+  st->print(BULLET"permitted subtypes:     "); permitted_subtypes()->print_value_on(st);     st->cr();
   if (java_mirror() != NULL) {
     st->print(BULLET"java mirror:       ");
     java_mirror()->print_value_on(st);
     st->cr();
   } else {
< prev index next >