mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-26 22:34:27 +02:00
8227046: compiler implementation for sealed classes
8225056: VM support for sealed classes 8227044: javax.lang.model for sealed classes 8227045: Preview APIs support for sealed classes 8227047: Javadoc for sealed types 8245854: JVM TI Specification for sealed classes Co-authored-by: Harold Seigel <harold.seigel@oracle.com> Co-authored-by: Jan Lahoda <jan.lahoda@oracle.com> Reviewed-by: mcimadamore, forax, darcy, dholmes, jlahoda, lfoltan, mchung, sspitsyn, vromero
This commit is contained in:
parent
567692e4ae
commit
d42bfef8a4
139 changed files with 6877 additions and 192 deletions
|
@ -218,6 +218,57 @@ bool InstanceKlass::has_nest_member(InstanceKlass* k, TRAPS) const {
|
|||
return false;
|
||||
}
|
||||
|
||||
// Called to verify that k is a permitted subclass of this class
|
||||
bool InstanceKlass::has_as_permitted_subclass(const InstanceKlass* k) const {
|
||||
Thread* THREAD = Thread::current();
|
||||
assert(k != NULL, "sanity check");
|
||||
assert(_permitted_subclasses != NULL && _permitted_subclasses != Universe::the_empty_short_array(),
|
||||
"unexpected empty _permitted_subclasses array");
|
||||
|
||||
if (log_is_enabled(Trace, class, sealed)) {
|
||||
ResourceMark rm(THREAD);
|
||||
log_trace(class, sealed)("Checking for permitted subclass of %s in %s",
|
||||
k->external_name(), this->external_name());
|
||||
}
|
||||
|
||||
// Check that the class and its super are in the same module.
|
||||
if (k->module() != this->module()) {
|
||||
ResourceMark rm(THREAD);
|
||||
log_trace(class, sealed)("Check failed for same module of permitted subclass %s and sealed class %s",
|
||||
k->external_name(), this->external_name());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!k->is_public() && !is_same_class_package(k)) {
|
||||
ResourceMark rm(THREAD);
|
||||
log_trace(class, sealed)("Check failed, subclass %s not public and not in the same package as 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_subclasses->length(); i++) {
|
||||
int cp_index = _permitted_subclasses->at(i);
|
||||
if (_constants->tag_at(cp_index).is_klass()) {
|
||||
Klass* k2 = _constants->klass_at(cp_index, THREAD);
|
||||
assert(!HAS_PENDING_EXCEPTION, "Unexpected exception");
|
||||
if (k2 == k) {
|
||||
log_trace(class, sealed)("- class is listed at permitted_subclasses[%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_subclasses[%d] => cp[%d]", i, cp_index);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
log_trace(class, sealed)("- class is NOT a permitted subclass!");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Return nest-host class, resolving, validating and saving it if needed.
|
||||
// In cases where this is called from a thread that cannot do classloading
|
||||
// (such as a native JIT thread) then we simply return NULL, which in turn
|
||||
|
@ -484,6 +535,7 @@ InstanceKlass::InstanceKlass(const ClassFileParser& parser, unsigned kind, Klass
|
|||
Klass(id),
|
||||
_nest_members(NULL),
|
||||
_nest_host(NULL),
|
||||
_permitted_subclasses(NULL),
|
||||
_record_components(NULL),
|
||||
_static_field_size(parser.static_field_size()),
|
||||
_nonstatic_oop_map_size(nonstatic_oop_map_size(parser.total_oop_map_count())),
|
||||
|
@ -665,6 +717,13 @@ void InstanceKlass::deallocate_contents(ClassLoaderData* loader_data) {
|
|||
}
|
||||
set_nest_members(NULL);
|
||||
|
||||
if (permitted_subclasses() != NULL &&
|
||||
permitted_subclasses() != Universe::the_empty_short_array() &&
|
||||
!permitted_subclasses()->is_shared()) {
|
||||
MetadataFactory::free_array<jushort>(loader_data, permitted_subclasses());
|
||||
}
|
||||
set_permitted_subclasses(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());
|
||||
|
@ -676,6 +735,12 @@ void InstanceKlass::deallocate_contents(ClassLoaderData* loader_data) {
|
|||
}
|
||||
}
|
||||
|
||||
bool InstanceKlass::is_sealed() const {
|
||||
return _permitted_subclasses != NULL &&
|
||||
_permitted_subclasses != Universe::the_empty_short_array() &&
|
||||
_permitted_subclasses->length() > 0;
|
||||
}
|
||||
|
||||
bool InstanceKlass::should_be_initialized() const {
|
||||
return !is_initialized();
|
||||
}
|
||||
|
@ -2414,6 +2479,7 @@ void InstanceKlass::metaspace_pointers_do(MetaspaceClosure* it) {
|
|||
}
|
||||
|
||||
it->push(&_nest_members);
|
||||
it->push(&_permitted_subclasses);
|
||||
it->push(&_record_components);
|
||||
}
|
||||
|
||||
|
@ -3342,6 +3408,7 @@ void InstanceKlass::print_on(outputStream* st) const {
|
|||
if (record_components() != NULL) {
|
||||
st->print(BULLET"record components: "); record_components()->print_value_on(st); st->cr();
|
||||
}
|
||||
st->print(BULLET"permitted subclasses: "); permitted_subclasses()->print_value_on(st); st->cr();
|
||||
if (java_mirror() != NULL) {
|
||||
st->print(BULLET"java mirror: ");
|
||||
java_mirror()->print_value_on(st);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue