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 Symbol* ObjArrayKlass::create_element_klass_array_name(JavaThread* current, Klass* element_klass) { 65 ResourceMark rm(current); 66 char* name_str = element_klass->name()->as_C_string(); 67 int len = element_klass->name()->utf8_length(); 68 char* new_str = NEW_RESOURCE_ARRAY_IN_THREAD(current, char, len + 4); 69 int idx = 0; 70 new_str[idx++] = JVM_SIGNATURE_ARRAY; 71 if (element_klass->is_instance_klass()) { // it could be an array or simple type 72 new_str[idx++] = JVM_SIGNATURE_CLASS; 73 } 74 memcpy(&new_str[idx], name_str, len * sizeof(char)); 75 idx += len; 76 if (element_klass->is_instance_klass()) { 77 new_str[idx++] = JVM_SIGNATURE_ENDCLASS; 78 } 79 new_str[idx] = '\0'; 80 return SymbolTable::new_symbol(new_str); 81 } 82 83 84 ObjArrayKlass* ObjArrayKlass::allocate_objArray_klass(ClassLoaderData* loader_data, 85 int n, Klass* element_klass, TRAPS) { 86 87 // Eagerly allocate the direct array supertype. 88 Klass* super_klass = nullptr; 89 if (!Universe::is_bootstrapping() || vmClasses::Object_klass_loaded()) { 90 assert(MultiArray_lock->holds_lock(THREAD), "must hold lock after bootstrapping"); 91 Klass* element_super = element_klass->super(); 92 if (element_super != nullptr) { 93 // The element type has a direct super. E.g., String[] has direct super of Object[]. 94 // Also, see if the element has secondary supertypes. 95 // We need an array type for each before creating this array type. 96 super_klass = element_super->array_klass(CHECK_NULL); 97 const Array<Klass*>* element_supers = element_klass->secondary_supers(); 98 for (int i = element_supers->length() - 1; i >= 0; i--) { 99 Klass* elem_super = element_supers->at(i); 100 elem_super->array_klass(CHECK_NULL); 101 } 102 // Fall through because inheritance is acyclic and we hold the global recursive lock to allocate all the arrays. 103 } else { 104 // The element type is already Object. Object[] has direct super of Object. 105 super_klass = vmClasses::Object_klass(); 106 } 107 } 108 109 // Create type name for klass. 110 Symbol* name = create_element_klass_array_name(THREAD, element_klass); 111 112 // Initialize instance variables 113 ObjArrayKlass* oak = ObjArrayKlass::allocate_klass(loader_data, n, element_klass, name, ArrayProperties::INVALID, CHECK_NULL); 114 115 ModuleEntry* module = oak->module(); 116 assert(module != nullptr, "No module entry for array"); 117 118 // Call complete_create_array_klass after all instance variables has been initialized. 119 ArrayKlass::complete_create_array_klass(oak, super_klass, module, CHECK_NULL); 120 121 // Add all classes to our internal class loader list here, 122 // including classes in the bootstrap (null) class loader. 123 // Do this step after creating the mirror so that if the 124 // mirror creation fails, loaded_classes_do() doesn't find 125 // an array class without a mirror. 126 loader_data->add_class(oak); 127 128 return oak; 129 } 130 131 ObjArrayKlass::ObjArrayKlass(int n, Klass* element_klass, Symbol* name, KlassKind kind, ArrayKlass::ArrayProperties props, markWord mk) : 132 ArrayKlass(name, kind, props, mk) { 133 set_dimension(n); 134 set_element_klass(element_klass); 135 set_next_refined_klass_klass(nullptr); 136 set_properties(props); 137 138 Klass* bk; 139 if (element_klass->is_objArray_klass()) { 140 bk = ObjArrayKlass::cast(element_klass)->bottom_klass(); 141 } else { 142 assert(!element_klass->is_refArray_klass(), "Sanity"); 143 bk = element_klass; 144 } 145 assert(bk != nullptr && (bk->is_instance_klass() || bk->is_typeArray_klass()), "invalid bottom klass"); 146 set_bottom_klass(bk); 147 set_class_loader_data(bk->class_loader_data()); 148 149 if (element_klass->is_array_klass()) { 150 set_lower_dimension(ArrayKlass::cast(element_klass)); 151 } 152 153 int lh = array_layout_helper(T_OBJECT); 154 if (ArrayKlass::is_null_restricted(props)) { 155 assert(n == 1, "Bytecode does not support null-free multi-dim"); 156 lh = layout_helper_set_null_free(lh); 157 #ifdef _LP64 158 assert(prototype_header().is_null_free_array(), "sanity"); 159 #endif 160 } 161 set_layout_helper(lh); 162 assert(is_array_klass(), "sanity"); 163 assert(is_objArray_klass(), "sanity"); 164 } 165 166 size_t ObjArrayKlass::oop_size(oop obj) const { 167 // In this assert, we cannot safely access the Klass* with compact headers, 168 // because size_given_klass() calls oop_size() on objects that might be 169 // concurrently forwarded, which would overwrite the Klass*. 170 assert(UseCompactObjectHeaders || obj->is_objArray(), "must be object array"); 171 // return objArrayOop(obj)->object_size(); 172 return obj->is_flatArray() ? flatArrayOop(obj)->object_size(layout_helper()) : refArrayOop(obj)->object_size(); 173 } 174 175 ArrayDescription ObjArrayKlass::array_layout_selection(Klass* element, ArrayProperties properties) { 176 // TODO FIXME: the layout selection should take the array size in consideration 177 // to avoid creation of arrays too big to be handled by the VM. See JDK-8233189 178 if (!UseArrayFlattening || element->is_array_klass() || element->is_identity_class() || element->is_abstract()) { 179 return ArrayDescription(RefArrayKlassKind, properties, LayoutKind::REFERENCE); 180 } 181 assert(element->is_final(), "Flat layouts below require monomorphic elements"); 182 InlineKlass* vk = InlineKlass::cast(element); 183 if (is_null_restricted(properties)) { 184 if (is_non_atomic(properties)) { 185 // Null-restricted + non-atomic 186 if (vk->maybe_flat_in_array() && vk->has_non_atomic_layout()) { 187 return ArrayDescription(FlatArrayKlassKind, properties, LayoutKind::NON_ATOMIC_FLAT); 188 } else { 189 return ArrayDescription(RefArrayKlassKind, properties, LayoutKind::REFERENCE); 190 } 191 } else { 192 // Null-restricted + atomic 193 if (vk->maybe_flat_in_array() && vk->is_naturally_atomic() && vk->has_non_atomic_layout()) { 194 return ArrayDescription(FlatArrayKlassKind, properties, LayoutKind::NON_ATOMIC_FLAT); 195 } else if (vk->maybe_flat_in_array() && vk->has_atomic_layout()) { 196 return ArrayDescription(FlatArrayKlassKind, properties, LayoutKind::ATOMIC_FLAT); 197 } else { 198 return ArrayDescription(RefArrayKlassKind, properties, LayoutKind::REFERENCE); 199 } 200 } 201 } else { 202 // nullable implies atomic, so the non-atomic property is ignored 203 if (vk->maybe_flat_in_array() && vk->has_nullable_atomic_layout()) { 204 return ArrayDescription(FlatArrayKlassKind, properties, LayoutKind::NULLABLE_ATOMIC_FLAT); 205 } else { 206 return ArrayDescription(RefArrayKlassKind, properties, LayoutKind::REFERENCE); 207 } 208 } 209 } 210 211 objArrayOop ObjArrayKlass::allocate_instance(int length, ArrayProperties props, TRAPS) { 212 check_array_allocation_length(length, arrayOopDesc::max_array_length(T_OBJECT), CHECK_NULL); 213 ObjArrayKlass* ak = klass_with_properties(props, THREAD); 214 size_t size = 0; 215 switch(ak->kind()) { 216 case Klass::RefArrayKlassKind: 217 size = refArrayOopDesc::object_size(length); 218 break; 219 case Klass::FlatArrayKlassKind: 220 size = flatArrayOopDesc::object_size(ak->layout_helper(), length); 221 break; 222 default: 223 ShouldNotReachHere(); 224 } 225 assert(size != 0, "Sanity check"); 226 objArrayOop array = (objArrayOop)Universe::heap()->array_allocate( 227 ak, size, length, 228 /* do_zero */ true, CHECK_NULL); 229 assert(array->is_refArray() || array->is_flatArray(), "Must be"); 230 objArrayHandle array_h(THREAD, array); 231 return array_h(); 232 } 233 234 oop ObjArrayKlass::multi_allocate(int rank, jint* sizes, TRAPS) { 235 int length = *sizes; 236 ArrayKlass* ld_klass = lower_dimension(); 237 // If length < 0 allocate will throw an exception. 238 ObjArrayKlass* oak = klass_with_properties(ArrayProperties::DEFAULT, CHECK_NULL); 239 assert(oak->is_refArray_klass() || oak->is_flatArray_klass(), "Must be"); 240 objArrayOop array = oak->allocate_instance(length, ArrayProperties::DEFAULT, CHECK_NULL); 241 objArrayHandle h_array (THREAD, array); 242 if (rank > 1) { 243 if (length != 0) { 244 for (int index = 0; index < length; index++) { 245 oop sub_array = ld_klass->multi_allocate(rank-1, &sizes[1], CHECK_NULL); 246 h_array->obj_at_put(index, sub_array); 247 } 248 } else { 249 // Since this array dimension has zero length, nothing will be 250 // allocated, however the lower dimension values must be checked 251 // for illegal values. 252 for (int i = 0; i < rank - 1; ++i) { 253 sizes += 1; 254 if (*sizes < 0) { 255 THROW_MSG_NULL(vmSymbols::java_lang_NegativeArraySizeException(), err_msg("%d", *sizes)); 256 } 257 } 258 } 259 } 260 return h_array(); 261 } 262 263 void ObjArrayKlass::copy_array(arrayOop s, int src_pos, arrayOop d, 264 int dst_pos, int length, TRAPS) { 265 assert(s->is_objArray(), "must be obj array"); 266 267 if (UseArrayFlattening) { 268 if (d->is_flatArray()) { 269 FlatArrayKlass::cast(d->klass())->copy_array(s, src_pos, d, dst_pos, length, THREAD); 270 return; 271 } 272 if (s->is_flatArray()) { 273 FlatArrayKlass::cast(s->klass())->copy_array(s, src_pos, d, dst_pos, length, THREAD); 274 return; 275 } 276 } 277 278 assert(s->is_refArray() && d->is_refArray(), "Must be"); 279 RefArrayKlass::cast(s->klass())->copy_array(s, src_pos, d, dst_pos, length, THREAD); 280 } 281 282 bool ObjArrayKlass::can_be_primary_super_slow() const { 283 if (!bottom_klass()->can_be_primary_super()) 284 // array of interfaces 285 return false; 286 else 287 return Klass::can_be_primary_super_slow(); 288 } 289 290 GrowableArray<Klass*>* ObjArrayKlass::compute_secondary_supers(int num_extra_slots, 291 Array<InstanceKlass*>* transitive_interfaces) { 292 assert(transitive_interfaces == nullptr, "sanity"); 293 // interfaces = { cloneable_klass, serializable_klass, elemSuper[], ... }; 294 const Array<Klass*>* elem_supers = element_klass()->secondary_supers(); 295 int num_elem_supers = elem_supers == nullptr ? 0 : elem_supers->length(); 296 int num_secondaries = num_extra_slots + 2 + num_elem_supers; 297 if (num_secondaries == 2) { 298 // Must share this for correct bootstrapping! 299 set_secondary_supers(Universe::the_array_interfaces_array(), 300 Universe::the_array_interfaces_bitmap()); 301 return nullptr; 302 } else { 303 GrowableArray<Klass*>* secondaries = new GrowableArray<Klass*>(num_elem_supers+2); 304 secondaries->push(vmClasses::Cloneable_klass()); 305 secondaries->push(vmClasses::Serializable_klass()); 306 for (int i = 0; i < num_elem_supers; i++) { 307 Klass* elem_super = elem_supers->at(i); 308 Klass* array_super = elem_super->array_klass_or_null(); 309 assert(array_super != nullptr, "must already have been created"); 310 secondaries->push(array_super); 311 } 312 return secondaries; 313 } 314 } 315 316 void ObjArrayKlass::initialize(TRAPS) { 317 bottom_klass()->initialize(THREAD); // dispatches to either InstanceKlass or TypeArrayKlass 318 } 319 320 void ObjArrayKlass::metaspace_pointers_do(MetaspaceClosure* it) { 321 ArrayKlass::metaspace_pointers_do(it); 322 it->push(&_element_klass); 323 it->push(&_bottom_klass); 324 if (_next_refined_array_klass != nullptr && !CDSConfig::is_dumping_dynamic_archive()) { 325 it->push(&_next_refined_array_klass); 326 } 327 } 328 329 #if INCLUDE_CDS 330 void ObjArrayKlass::restore_unshareable_info(ClassLoaderData* loader_data, Handle protection_domain, TRAPS) { 331 ArrayKlass::restore_unshareable_info(loader_data, protection_domain, CHECK); 332 if (_next_refined_array_klass != nullptr) { 333 _next_refined_array_klass->restore_unshareable_info(loader_data, protection_domain, CHECK); 334 } 335 } 336 337 void ObjArrayKlass::remove_unshareable_info() { 338 ArrayKlass::remove_unshareable_info(); 339 if (_next_refined_array_klass != nullptr && !CDSConfig::is_dumping_dynamic_archive()) { 340 _next_refined_array_klass->remove_unshareable_info(); 341 } else { 342 _next_refined_array_klass = nullptr; 343 } 344 } 345 346 void ObjArrayKlass::remove_java_mirror() { 347 ArrayKlass::remove_java_mirror(); 348 if (_next_refined_array_klass != nullptr && !CDSConfig::is_dumping_dynamic_archive()) { 349 _next_refined_array_klass->remove_java_mirror(); 350 } 351 } 352 #endif // INCLUDE_CDS 353 354 u2 ObjArrayKlass::compute_modifier_flags() const { 355 // The modifier for an objectArray is the same as its element 356 assert (element_klass() != nullptr, "should be initialized"); 357 358 // Return the flags of the bottom element type. 359 u2 element_flags = bottom_klass()->compute_modifier_flags(); 360 361 int identity_flag = (Arguments::enable_preview()) ? JVM_ACC_IDENTITY : 0; 362 363 return (element_flags & (JVM_ACC_PUBLIC | JVM_ACC_PRIVATE | JVM_ACC_PROTECTED)) 364 | (identity_flag | JVM_ACC_ABSTRACT | JVM_ACC_FINAL); 365 } 366 367 ModuleEntry* ObjArrayKlass::module() const { 368 assert(bottom_klass() != nullptr, "ObjArrayKlass returned unexpected null bottom_klass"); 369 // The array is defined in the module of its bottom class 370 return bottom_klass()->module(); 371 } 372 373 PackageEntry* ObjArrayKlass::package() const { 374 assert(bottom_klass() != nullptr, "ObjArrayKlass returned unexpected null bottom_klass"); 375 return bottom_klass()->package(); 376 } 377 378 ObjArrayKlass* ObjArrayKlass::klass_with_properties(ArrayKlass::ArrayProperties props, TRAPS) { 379 assert(props != ArrayProperties::INVALID, "Sanity check"); 380 381 if (properties() == props) { 382 assert(is_refArray_klass() || is_flatArray_klass(), "Must be a concrete array klass"); 383 return this; 384 } 385 386 ObjArrayKlass* ak = next_refined_array_klass_acquire(); 387 if (ak == nullptr) { 388 // Ensure atomic creation of refined array klasses 389 RecursiveLocker rl(MultiArray_lock, THREAD); 390 391 if (next_refined_array_klass() == nullptr) { 392 ArrayDescription ad = ObjArrayKlass::array_layout_selection(element_klass(), props); 393 switch (ad._kind) { 394 case Klass::RefArrayKlassKind: { 395 ak = RefArrayKlass::allocate_refArray_klass(class_loader_data(), dimension(), element_klass(), props, CHECK_NULL); 396 break; 397 } 398 case Klass::FlatArrayKlassKind: { 399 assert(dimension() == 1, "Flat arrays can only be dimension 1 arrays"); 400 ak = FlatArrayKlass::allocate_klass(element_klass(), props, ad._layout_kind, CHECK_NULL); 401 break; 402 } 403 default: 404 ShouldNotReachHere(); 405 } 406 release_set_next_refined_klass(ak); 407 } 408 } 409 410 ak = next_refined_array_klass(); 411 assert(ak != nullptr, "should be set"); 412 THREAD->check_possible_safepoint(); 413 return ak->klass_with_properties(props, THREAD); // why not CHECK_NULL ? 414 } 415 416 417 // Printing 418 419 void ObjArrayKlass::print_on(outputStream* st) const { 420 #ifndef PRODUCT 421 Klass::print_on(st); 422 st->print(" - element klass: "); 423 element_klass()->print_value_on(st); 424 st->cr(); 425 #endif //PRODUCT 426 } 427 428 void ObjArrayKlass::print_value_on(outputStream* st) const { 429 assert(is_klass(), "must be klass"); 430 431 element_klass()->print_value_on(st); 432 st->print("[]"); 433 } 434 435 #ifndef PRODUCT 436 437 void ObjArrayKlass::oop_print_on(oop obj, outputStream* st) { 438 ShouldNotReachHere(); 439 } 440 441 #endif //PRODUCT 442 443 void ObjArrayKlass::oop_print_value_on(oop obj, outputStream* st) { 444 ShouldNotReachHere(); 445 } 446 447 const char* ObjArrayKlass::internal_name() const { 448 return external_name(); 449 } 450 451 452 // Verification 453 454 void ObjArrayKlass::verify_on(outputStream* st) { 455 ArrayKlass::verify_on(st); 456 guarantee(element_klass()->is_klass(), "should be klass"); 457 guarantee(bottom_klass()->is_klass(), "should be klass"); 458 Klass* bk = bottom_klass(); 459 guarantee(bk->is_instance_klass() || bk->is_typeArray_klass() || bk->is_flatArray_klass(), 460 "invalid bottom klass"); 461 } 462 463 void ObjArrayKlass::oop_verify_on(oop obj, outputStream* st) { 464 ArrayKlass::oop_verify_on(obj, st); 465 guarantee(obj->is_objArray(), "must be objArray"); 466 guarantee(obj->is_null_free_array() || (!is_null_free_array_klass()), "null-free klass but not object"); 467 objArrayOop oa = objArrayOop(obj); 468 for(int index = 0; index < oa->length(); index++) { 469 guarantee(oopDesc::is_oop_or_null(oa->obj_at(index)), "should be oop"); 470 } 471 }