1 /* 2 * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25 #include "cds/cdsConfig.hpp" 26 #include "classfile/moduleEntry.hpp" 27 #include "classfile/packageEntry.hpp" 28 #include "classfile/symbolTable.hpp" 29 #include "classfile/vmClasses.hpp" 30 #include "classfile/vmSymbols.hpp" 31 #include "gc/shared/collectedHeap.inline.hpp" 32 #include "memory/iterator.inline.hpp" 33 #include "memory/metadataFactory.hpp" 34 #include "memory/metaspaceClosure.hpp" 35 #include "memory/oopFactory.hpp" 36 #include "memory/resourceArea.hpp" 37 #include "memory/universe.hpp" 38 #include "oops/arrayKlass.hpp" 39 #include "oops/flatArrayKlass.hpp" 40 #include "oops/instanceKlass.hpp" 41 #include "oops/klass.inline.hpp" 42 #include "oops/markWord.hpp" 43 #include "oops/objArrayKlass.inline.hpp" 44 #include "oops/objArrayOop.inline.hpp" 45 #include "oops/oop.inline.hpp" 46 #include "oops/refArrayKlass.hpp" 47 #include "oops/symbol.hpp" 48 #include "runtime/arguments.hpp" 49 #include "runtime/handles.inline.hpp" 50 #include "runtime/mutexLocker.hpp" 51 #include "utilities/macros.hpp" 52 53 ObjArrayKlass* ObjArrayKlass::allocate_klass(ClassLoaderData* loader_data, int n, 54 Klass* k, Symbol* name, ArrayKlass::ArrayProperties props, 55 TRAPS) { 56 assert(ObjArrayKlass::header_size() <= InstanceKlass::header_size(), 57 "array klasses must be same size as InstanceKlass"); 58 59 int size = ArrayKlass::static_size(ObjArrayKlass::header_size()); 60 61 return new (loader_data, size, THREAD) ObjArrayKlass(n, k, name, Kind, props, ArrayKlass::is_null_restricted(props) ? markWord::null_free_array_prototype() : markWord::prototype()); 62 } 63 64 ObjArrayKlass* ObjArrayKlass::allocate_objArray_klass(ClassLoaderData* loader_data, 65 int n, Klass* element_klass, TRAPS) { 66 67 // Eagerly allocate the direct array supertype. 68 Klass* super_klass = nullptr; 69 if (!Universe::is_bootstrapping() || vmClasses::Object_klass_loaded()) { 70 assert(MultiArray_lock->holds_lock(THREAD), "must hold lock after bootstrapping"); 71 Klass* element_super = element_klass->super(); 72 if (element_super != nullptr) { 73 // The element type has a direct super. E.g., String[] has direct super of Object[]. 74 // Also, see if the element has secondary supertypes. 75 // We need an array type for each before creating this array type. 76 super_klass = element_super->array_klass(CHECK_NULL); 77 const Array<Klass*>* element_supers = element_klass->secondary_supers(); 78 for (int i = element_supers->length() - 1; i >= 0; i--) { 79 Klass* elem_super = element_supers->at(i); 80 elem_super->array_klass(CHECK_NULL); 81 } 82 // Fall through because inheritance is acyclic and we hold the global recursive lock to allocate all the arrays. 83 } else { 84 // The element type is already Object. Object[] has direct super of Object. 85 super_klass = vmClasses::Object_klass(); 86 } 87 } 88 89 // Create type name for klass. 90 Symbol* name = ArrayKlass::create_element_klass_array_name(element_klass, CHECK_NULL); 91 92 // Initialize instance variables 93 ObjArrayKlass* oak = ObjArrayKlass::allocate_klass(loader_data, n, element_klass, name, ArrayProperties::INVALID, CHECK_NULL); 94 95 ModuleEntry* module = oak->module(); 96 assert(module != nullptr, "No module entry for array"); 97 98 // Call complete_create_array_klass after all instance variables has been initialized. 99 ArrayKlass::complete_create_array_klass(oak, super_klass, module, CHECK_NULL); 100 101 // Add all classes to our internal class loader list here, 102 // including classes in the bootstrap (null) class loader. 103 // Do this step after creating the mirror so that if the 104 // mirror creation fails, loaded_classes_do() doesn't find 105 // an array class without a mirror. 106 loader_data->add_class(oak); 107 108 return oak; 109 } 110 111 ObjArrayKlass::ObjArrayKlass(int n, Klass* element_klass, Symbol* name, KlassKind kind, ArrayKlass::ArrayProperties props, markWord mk) : 112 ArrayKlass(name, kind, props, mk) { 113 set_dimension(n); 114 set_element_klass(element_klass); 115 set_next_refined_klass_klass(nullptr); 116 set_properties(props); 117 118 Klass* bk; 119 if (element_klass->is_objArray_klass()) { 120 bk = ObjArrayKlass::cast(element_klass)->bottom_klass(); 121 } else { 122 assert(!element_klass->is_refArray_klass(), "Sanity"); 123 bk = element_klass; 124 } 125 assert(bk != nullptr && (bk->is_instance_klass() || bk->is_typeArray_klass()), "invalid bottom klass"); 126 set_bottom_klass(bk); 127 set_class_loader_data(bk->class_loader_data()); 128 129 if (element_klass->is_array_klass()) { 130 set_lower_dimension(ArrayKlass::cast(element_klass)); 131 } 132 133 int lh = array_layout_helper(T_OBJECT); 134 if (ArrayKlass::is_null_restricted(props)) { 135 assert(n == 1, "Bytecode does not support null-free multi-dim"); 136 lh = layout_helper_set_null_free(lh); 137 #ifdef _LP64 138 assert(prototype_header().is_null_free_array(), "sanity"); 139 #endif 140 } 141 set_layout_helper(lh); 142 assert(is_array_klass(), "sanity"); 143 assert(is_objArray_klass(), "sanity"); 144 } 145 146 size_t ObjArrayKlass::oop_size(oop obj) const { 147 // In this assert, we cannot safely access the Klass* with compact headers, 148 // because size_given_klass() calls oop_size() on objects that might be 149 // concurrently forwarded, which would overwrite the Klass*. 150 assert(UseCompactObjectHeaders || obj->is_objArray(), "must be object array"); 151 // return objArrayOop(obj)->object_size(); 152 return obj->is_flatArray() ? flatArrayOop(obj)->object_size(layout_helper()) : refArrayOop(obj)->object_size(); 153 } 154 155 ArrayDescription ObjArrayKlass::array_layout_selection(Klass* element, ArrayProperties properties) { 156 // TODO FIXME: the layout selection should take the array size in consideration 157 // to avoid creation of arrays too big to be handled by the VM. See JDK-8233189 158 if (!UseArrayFlattening || element->is_array_klass() || element->is_identity_class() || element->is_abstract()) { 159 return ArrayDescription(RefArrayKlassKind, properties, LayoutKind::REFERENCE); 160 } 161 assert(element->is_final(), "Flat layouts below require monomorphic elements"); 162 InlineKlass* vk = InlineKlass::cast(element); 163 if (is_null_restricted(properties)) { 164 if (is_non_atomic(properties)) { 165 // Null-restricted + non-atomic 166 if (vk->maybe_flat_in_array() && vk->has_non_atomic_layout()) { 167 return ArrayDescription(FlatArrayKlassKind, properties, LayoutKind::NON_ATOMIC_FLAT); 168 } else { 169 return ArrayDescription(RefArrayKlassKind, properties, LayoutKind::REFERENCE); 170 } 171 } else { 172 // Null-restricted + atomic 173 if (vk->maybe_flat_in_array() && vk->is_naturally_atomic() && vk->has_non_atomic_layout()) { 174 return ArrayDescription(FlatArrayKlassKind, properties, LayoutKind::NON_ATOMIC_FLAT); 175 } else if (vk->maybe_flat_in_array() && vk->has_atomic_layout()) { 176 return ArrayDescription(FlatArrayKlassKind, properties, LayoutKind::ATOMIC_FLAT); 177 } else { 178 return ArrayDescription(RefArrayKlassKind, properties, LayoutKind::REFERENCE); 179 } 180 } 181 } else { 182 // nullable implies atomic, so the non-atomic property is ignored 183 if (vk->maybe_flat_in_array() && vk->has_nullable_atomic_layout()) { 184 return ArrayDescription(FlatArrayKlassKind, properties, LayoutKind::NULLABLE_ATOMIC_FLAT); 185 } else { 186 return ArrayDescription(RefArrayKlassKind, properties, LayoutKind::REFERENCE); 187 } 188 } 189 } 190 191 objArrayOop ObjArrayKlass::allocate_instance(int length, ArrayProperties props, TRAPS) { 192 check_array_allocation_length(length, arrayOopDesc::max_array_length(T_OBJECT), CHECK_NULL); 193 ObjArrayKlass* ak = klass_with_properties(props, THREAD); 194 size_t size = 0; 195 switch(ak->kind()) { 196 case Klass::RefArrayKlassKind: 197 size = refArrayOopDesc::object_size(length); 198 break; 199 case Klass::FlatArrayKlassKind: 200 size = flatArrayOopDesc::object_size(ak->layout_helper(), length); 201 break; 202 default: 203 ShouldNotReachHere(); 204 } 205 assert(size != 0, "Sanity check"); 206 objArrayOop array = (objArrayOop)Universe::heap()->array_allocate( 207 ak, size, length, 208 /* do_zero */ true, CHECK_NULL); 209 assert(array->is_refArray() || array->is_flatArray(), "Must be"); 210 objArrayHandle array_h(THREAD, array); 211 return array_h(); 212 } 213 214 oop ObjArrayKlass::multi_allocate(int rank, jint* sizes, TRAPS) { 215 int length = *sizes; 216 ArrayKlass* ld_klass = lower_dimension(); 217 // If length < 0 allocate will throw an exception. 218 ObjArrayKlass* oak = klass_with_properties(ArrayProperties::DEFAULT, CHECK_NULL); 219 assert(oak->is_refArray_klass() || oak->is_flatArray_klass(), "Must be"); 220 objArrayOop array = oak->allocate_instance(length, ArrayProperties::DEFAULT, CHECK_NULL); 221 objArrayHandle h_array (THREAD, array); 222 if (rank > 1) { 223 if (length != 0) { 224 for (int index = 0; index < length; index++) { 225 oop sub_array = ld_klass->multi_allocate(rank-1, &sizes[1], CHECK_NULL); 226 h_array->obj_at_put(index, sub_array); 227 } 228 } else { 229 // Since this array dimension has zero length, nothing will be 230 // allocated, however the lower dimension values must be checked 231 // for illegal values. 232 for (int i = 0; i < rank - 1; ++i) { 233 sizes += 1; 234 if (*sizes < 0) { 235 THROW_MSG_NULL(vmSymbols::java_lang_NegativeArraySizeException(), err_msg("%d", *sizes)); 236 } 237 } 238 } 239 } 240 return h_array(); 241 } 242 243 void ObjArrayKlass::copy_array(arrayOop s, int src_pos, arrayOop d, 244 int dst_pos, int length, TRAPS) { 245 assert(s->is_objArray(), "must be obj array"); 246 247 if (UseArrayFlattening) { 248 if (d->is_flatArray()) { 249 FlatArrayKlass::cast(d->klass())->copy_array(s, src_pos, d, dst_pos, length, THREAD); 250 return; 251 } 252 if (s->is_flatArray()) { 253 FlatArrayKlass::cast(s->klass())->copy_array(s, src_pos, d, dst_pos, length, THREAD); 254 return; 255 } 256 } 257 258 assert(s->is_refArray() && d->is_refArray(), "Must be"); 259 RefArrayKlass::cast(s->klass())->copy_array(s, src_pos, d, dst_pos, length, THREAD); 260 } 261 262 bool ObjArrayKlass::can_be_primary_super_slow() const { 263 if (!bottom_klass()->can_be_primary_super()) 264 // array of interfaces 265 return false; 266 else 267 return Klass::can_be_primary_super_slow(); 268 } 269 270 GrowableArray<Klass*>* ObjArrayKlass::compute_secondary_supers(int num_extra_slots, 271 Array<InstanceKlass*>* transitive_interfaces) { 272 assert(transitive_interfaces == nullptr, "sanity"); 273 // interfaces = { cloneable_klass, serializable_klass, elemSuper[], ... }; 274 const Array<Klass*>* elem_supers = element_klass()->secondary_supers(); 275 int num_elem_supers = elem_supers == nullptr ? 0 : elem_supers->length(); 276 int num_secondaries = num_extra_slots + 2 + num_elem_supers; 277 if (num_secondaries == 2) { 278 // Must share this for correct bootstrapping! 279 set_secondary_supers(Universe::the_array_interfaces_array(), 280 Universe::the_array_interfaces_bitmap()); 281 return nullptr; 282 } else { 283 GrowableArray<Klass*>* secondaries = new GrowableArray<Klass*>(num_elem_supers+2); 284 secondaries->push(vmClasses::Cloneable_klass()); 285 secondaries->push(vmClasses::Serializable_klass()); 286 for (int i = 0; i < num_elem_supers; i++) { 287 Klass* elem_super = elem_supers->at(i); 288 Klass* array_super = elem_super->array_klass_or_null(); 289 assert(array_super != nullptr, "must already have been created"); 290 secondaries->push(array_super); 291 } 292 return secondaries; 293 } 294 } 295 296 void ObjArrayKlass::initialize(TRAPS) { 297 bottom_klass()->initialize(THREAD); // dispatches to either InstanceKlass or TypeArrayKlass 298 } 299 300 void ObjArrayKlass::metaspace_pointers_do(MetaspaceClosure* it) { 301 ArrayKlass::metaspace_pointers_do(it); 302 it->push(&_element_klass); 303 it->push(&_bottom_klass); 304 if (_next_refined_array_klass != nullptr && !CDSConfig::is_dumping_dynamic_archive()) { 305 it->push(&_next_refined_array_klass); 306 } 307 } 308 309 void ObjArrayKlass::restore_unshareable_info(ClassLoaderData* loader_data, Handle protection_domain, TRAPS) { 310 ArrayKlass::restore_unshareable_info(loader_data, protection_domain, CHECK); 311 if (_next_refined_array_klass != nullptr) { 312 _next_refined_array_klass->restore_unshareable_info(loader_data, protection_domain, CHECK); 313 } 314 } 315 316 void ObjArrayKlass::remove_unshareable_info() { 317 ArrayKlass::remove_unshareable_info(); 318 if (_next_refined_array_klass != nullptr && !CDSConfig::is_dumping_dynamic_archive()) { 319 _next_refined_array_klass->remove_unshareable_info(); 320 } else { 321 _next_refined_array_klass = nullptr; 322 } 323 } 324 325 void ObjArrayKlass::remove_java_mirror() { 326 ArrayKlass::remove_java_mirror(); 327 if (_next_refined_array_klass != nullptr) { 328 _next_refined_array_klass->remove_java_mirror(); 329 } 330 } 331 332 u2 ObjArrayKlass::compute_modifier_flags() const { 333 // The modifier for an objectArray is the same as its element 334 assert (element_klass() != nullptr, "should be initialized"); 335 336 // Return the flags of the bottom element type. 337 u2 element_flags = bottom_klass()->compute_modifier_flags(); 338 339 int identity_flag = (Arguments::enable_preview()) ? JVM_ACC_IDENTITY : 0; 340 341 return (element_flags & (JVM_ACC_PUBLIC | JVM_ACC_PRIVATE | JVM_ACC_PROTECTED)) 342 | (identity_flag | JVM_ACC_ABSTRACT | JVM_ACC_FINAL); 343 } 344 345 ModuleEntry* ObjArrayKlass::module() const { 346 assert(bottom_klass() != nullptr, "ObjArrayKlass returned unexpected null bottom_klass"); 347 // The array is defined in the module of its bottom class 348 return bottom_klass()->module(); 349 } 350 351 PackageEntry* ObjArrayKlass::package() const { 352 assert(bottom_klass() != nullptr, "ObjArrayKlass returned unexpected null bottom_klass"); 353 return bottom_klass()->package(); 354 } 355 356 ObjArrayKlass* ObjArrayKlass::klass_with_properties(ArrayKlass::ArrayProperties props, TRAPS) { 357 assert(props != ArrayProperties::INVALID, "Sanity check"); 358 359 if (properties() == props) { 360 assert(is_refArray_klass() || is_flatArray_klass(), "Must be a concrete array klass"); 361 return this; 362 } 363 364 ObjArrayKlass* ak = next_refined_array_klass_acquire(); 365 if (ak == nullptr) { 366 // Ensure atomic creation of refined array klasses 367 RecursiveLocker rl(MultiArray_lock, THREAD); 368 369 if (next_refined_array_klass() == nullptr) { 370 ArrayDescription ad = ObjArrayKlass::array_layout_selection(element_klass(), props); 371 switch (ad._kind) { 372 case Klass::RefArrayKlassKind: { 373 ak = RefArrayKlass::allocate_refArray_klass(class_loader_data(), dimension(), element_klass(), props, CHECK_NULL); 374 break; 375 } 376 case Klass::FlatArrayKlassKind: { 377 assert(dimension() == 1, "Flat arrays can only be dimension 1 arrays"); 378 ak = FlatArrayKlass::allocate_klass(element_klass(), props, ad._layout_kind, CHECK_NULL); 379 break; 380 } 381 default: 382 ShouldNotReachHere(); 383 } 384 release_set_next_refined_klass(ak); 385 } 386 } 387 388 ak = next_refined_array_klass(); 389 assert(ak != nullptr, "should be set"); 390 THREAD->check_possible_safepoint(); 391 return ak->klass_with_properties(props, THREAD); // why not CHECK_NULL ? 392 } 393 394 395 // Printing 396 397 void ObjArrayKlass::print_on(outputStream* st) const { 398 #ifndef PRODUCT 399 Klass::print_on(st); 400 st->print(" - element klass: "); 401 element_klass()->print_value_on(st); 402 st->cr(); 403 #endif //PRODUCT 404 } 405 406 void ObjArrayKlass::print_value_on(outputStream* st) const { 407 assert(is_klass(), "must be klass"); 408 409 element_klass()->print_value_on(st); 410 st->print("[]"); 411 } 412 413 #ifndef PRODUCT 414 415 void ObjArrayKlass::oop_print_on(oop obj, outputStream* st) { 416 ShouldNotReachHere(); 417 } 418 419 #endif //PRODUCT 420 421 void ObjArrayKlass::oop_print_value_on(oop obj, outputStream* st) { 422 ShouldNotReachHere(); 423 } 424 425 const char* ObjArrayKlass::internal_name() const { 426 return external_name(); 427 } 428 429 430 // Verification 431 432 void ObjArrayKlass::verify_on(outputStream* st) { 433 ArrayKlass::verify_on(st); 434 guarantee(element_klass()->is_klass(), "should be klass"); 435 guarantee(bottom_klass()->is_klass(), "should be klass"); 436 Klass* bk = bottom_klass(); 437 guarantee(bk->is_instance_klass() || bk->is_typeArray_klass() || bk->is_flatArray_klass(), 438 "invalid bottom klass"); 439 } 440 441 void ObjArrayKlass::oop_verify_on(oop obj, outputStream* st) { 442 ArrayKlass::oop_verify_on(obj, st); 443 guarantee(obj->is_objArray(), "must be objArray"); 444 guarantee(obj->is_null_free_array() || (!is_null_free_array_klass()), "null-free klass but not object"); 445 objArrayOop oa = objArrayOop(obj); 446 for(int index = 0; index < oa->length(); index++) { 447 guarantee(oopDesc::is_oop_or_null(oa->obj_at(index)), "should be oop"); 448 } 449 }