diff --git a/src/hotspot/share/classfile/classFileParser.cpp b/src/hotspot/share/classfile/classFileParser.cpp index 50ecaaa0cd7..d60e1d4addd 100644 --- a/src/hotspot/share/classfile/classFileParser.cpp +++ b/src/hotspot/share/classfile/classFileParser.cpp @@ -5057,6 +5057,11 @@ static Array* compute_transitive_interfaces(const InstanceKlass* // length will be less than the max_transitive_size if duplicates were removed const int length = result->length(); assert(length <= max_transitive_size, "just checking"); + + if (length == 1 && result->at(0) == SystemDictionary::IdentityObject_klass()) { + return Universe::the_single_IdentityObject_klass_array(); + } + Array* const new_result = MetadataFactory::new_array(loader_data, length, CHECK_NULL); for (int i = 0; i < length; i++) { @@ -6396,6 +6401,10 @@ void ClassFileParser::fill_instance_klass(InstanceKlass* ik, bool changed_by_loa // it's official set_klass(ik); + if (ik->name() == vmSymbols::java_lang_IdentityObject()) { + Universe::initialize_the_single_IdentityObject_klass_array(ik, CHECK); + } + debug_only(ik->verify();) } @@ -7047,6 +7056,8 @@ void ClassFileParser::post_process_parsed_stream(const ClassFileStream* const st int itfs_len = _temp_local_interfaces->length(); if (itfs_len == 0) { _local_interfaces = Universe::the_empty_instance_klass_array(); + } else if (itfs_len == 1 && _temp_local_interfaces->at(0) == SystemDictionary::IdentityObject_klass()) { + _local_interfaces = Universe::the_single_IdentityObject_klass_array(); } else { _local_interfaces = MetadataFactory::new_array(_loader_data, itfs_len, NULL, CHECK); for (int i = 0; i < itfs_len; i++) { diff --git a/src/hotspot/share/memory/universe.cpp b/src/hotspot/share/memory/universe.cpp index e2ea1ec6ed8..af19302b459 100644 --- a/src/hotspot/share/memory/universe.cpp +++ b/src/hotspot/share/memory/universe.cpp @@ -139,6 +139,7 @@ Array* Universe::_the_empty_int_array = NULL; Array* Universe::_the_empty_short_array = NULL; Array* Universe::_the_empty_klass_array = NULL; Array* Universe::_the_empty_instance_klass_array = NULL; +Array* Universe::_the_single_IdentityObject_klass_array = NULL; Array* Universe::_the_empty_method_array = NULL; // These variables are guarded by FullGCALot_lock. @@ -224,6 +225,7 @@ void Universe::metaspace_pointers_do(MetaspaceClosure* it) { it->push(&_the_empty_instance_klass_array); it->push(&_the_empty_method_array); it->push(&_the_array_interfaces_array); + it->push(&_the_single_IdentityObject_klass_array); _finalizer_register_cache->metaspace_pointers_do(it); _loader_addClass_cache->metaspace_pointers_do(it); @@ -262,6 +264,7 @@ void Universe::serialize(SerializeClosure* f) { f->do_ptr((void**)&_the_empty_method_array); f->do_ptr((void**)&_the_empty_klass_array); f->do_ptr((void**)&_the_empty_instance_klass_array); + f->do_ptr((void**)&_the_single_IdentityObject_klass_array); _finalizer_register_cache->serialize(f); _loader_addClass_cache->serialize(f); _throw_illegal_access_error_cache->serialize(f); @@ -343,6 +346,8 @@ void Universe::genesis(TRAPS) { assert(_the_array_interfaces_array->at(2) == SystemDictionary::IdentityObject_klass(), "u3"); + assert(_the_single_IdentityObject_klass_array->at(0) == + SystemDictionary::IdentityObject_klass(), "u3"); } else #endif { @@ -471,6 +476,14 @@ void Universe::initialize_basic_type_mirrors(TRAPS) { //_mirrors[T_ARRAY] = _object_klass->java_mirror(); } +void Universe::initialize_the_single_IdentityObject_klass_array(InstanceKlass* ik, TRAPS) { + assert(_the_single_IdentityObject_klass_array == NULL, "Must not be initialized twice"); + assert(ik->name() == vmSymbols::java_lang_IdentityObject(), "Must be"); + Array* array = MetadataFactory::new_array(ik->class_loader_data(), 1, NULL, CHECK); + array->at_put(0, ik); + _the_single_IdentityObject_klass_array = array; + } + void Universe::fixup_mirrors(TRAPS) { // Bootstrap problem: all classes gets a mirror (java.lang.Class instance) assigned eagerly, // but we cannot do that for classes created before java.lang.Class is loaded. Here we simply diff --git a/src/hotspot/share/memory/universe.hpp b/src/hotspot/share/memory/universe.hpp index f5a55b56ebc..1880db33401 100644 --- a/src/hotspot/share/memory/universe.hpp +++ b/src/hotspot/share/memory/universe.hpp @@ -136,6 +136,7 @@ class Universe: AllStatic { static Array* _the_empty_short_array; // Canonicalized short array static Array* _the_empty_klass_array; // Canonicalized klass array static Array* _the_empty_instance_klass_array; // Canonicalized instance klass array + static Array* _the_single_IdentityObject_klass_array; static Array* _the_empty_method_array; // Canonicalized method array static Array* _the_array_interfaces_array; @@ -312,6 +313,12 @@ class Universe: AllStatic { static Array* the_empty_method_array() { return _the_empty_method_array; } static Array* the_empty_klass_array() { return _the_empty_klass_array; } static Array* the_empty_instance_klass_array() { return _the_empty_instance_klass_array; } + static Array* the_single_IdentityObject_klass_array() { + assert(_the_single_IdentityObject_klass_array != NULL, "Must be initialized before use"); + assert(_the_single_IdentityObject_klass_array->length() == 1, "Sanity check"); + return _the_single_IdentityObject_klass_array; + } + static void initialize_the_single_IdentityObject_klass_array(InstanceKlass* ik, TRAPS); // OutOfMemoryError support. Returns an error with the required message. The returned error // may or may not have a backtrace. If error has a backtrace then the stack trace is already diff --git a/src/hotspot/share/oops/instanceKlass.cpp b/src/hotspot/share/oops/instanceKlass.cpp index e7332fc0e59..4e104b2636a 100644 --- a/src/hotspot/share/oops/instanceKlass.cpp +++ b/src/hotspot/share/oops/instanceKlass.cpp @@ -537,14 +537,16 @@ void InstanceKlass::deallocate_interfaces(ClassLoaderData* loader_data, // check that the interfaces don't come from super class Array* sti = (super_klass == NULL) ? NULL : InstanceKlass::cast(super_klass)->transitive_interfaces(); - if (ti != sti && ti != NULL && !ti->is_shared()) { + if (ti != sti && ti != NULL && !ti->is_shared() && + ti != Universe::the_single_IdentityObject_klass_array()) { MetadataFactory::free_array(loader_data, ti); } } // local interfaces can be empty if (local_interfaces != Universe::the_empty_instance_klass_array() && - local_interfaces != NULL && !local_interfaces->is_shared()) { + local_interfaces != NULL && !local_interfaces->is_shared() && + local_interfaces != Universe::the_single_IdentityObject_klass_array()) { MetadataFactory::free_array(loader_data, local_interfaces); } }