1 /* 2 * Copyright (c) 2024, 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/aotClassInitializer.hpp" 26 #include "cds/aotLinkedClassBulkLoader.hpp" 27 #include "cds/archiveBuilder.hpp" 28 #include "cds/cdsConfig.hpp" 29 #include "cds/heapShared.hpp" 30 #include "cds/regeneratedClasses.hpp" 31 #include "classfile/symbolTable.hpp" 32 #include "classfile/systemDictionaryShared.hpp" 33 #include "classfile/vmSymbols.hpp" 34 #include "dumpTimeClassInfo.inline.hpp" 35 #include "memory/resourceArea.hpp" 36 #include "oops/fieldStreams.inline.hpp" 37 #include "oops/instanceKlass.inline.hpp" 38 #include "oops/symbol.hpp" 39 #include "runtime/fieldDescriptor.inline.hpp" 40 #include "runtime/java.hpp" 41 #include "runtime/javaCalls.hpp" 42 #include "runtime/mutexLocker.hpp" 43 44 DEBUG_ONLY(InstanceKlass* _aot_init_class = nullptr;) 45 46 bool AOTClassInitializer::can_archive_initialized_mirror(InstanceKlass* ik) { 47 assert(!ArchiveBuilder::is_active() || !ArchiveBuilder::current()->is_in_buffer_space(ik), "must be source klass"); 48 if (!CDSConfig::is_initing_classes_at_dump_time()) { 49 return false; 50 } 51 52 if (RegeneratedClasses::is_regenerated_object(ik)) { 53 ik = RegeneratedClasses::get_original_object(ik); 54 } 55 56 if (!ik->is_initialized() && !ik->is_being_initialized()) { 57 return false; 58 } 59 60 // About "static field that may hold a different value" errors: 61 // 62 // Automatic selection for aot-inited classes 63 // ========================================== 64 // 65 // When CDSConfig::is_initing_classes_at_dump_time is enabled, 66 // AOTArtifactFinder::find_artifacts() finds the classes of all 67 // heap objects that are reachable from HeapShared::_run_time_special_subgraph, 68 // and mark these classes as aot-inited. This preserves the initialized 69 // mirrors of these classes, and their <clinit> methods are NOT executed 70 // at runtime. See aotArtifactFinder.hpp for more info. 71 // 72 // For example, with -XX:+AOTInvokeDynamicLinking, _run_time_special_subgraph 73 // will contain some DirectMethodHandle objects. As a result, the DirectMethodHandle 74 // class is automatically marked as aot-inited. 75 // 76 // When a class is aot-inited, its static fields are already set up 77 // by executing the <clinit> method at AOT assembly time. Later on 78 // in the production run, when the class would normally be 79 // initialized, the VM performs guarding and synchronization as if 80 // it were going to run the <clinit> again, but instead it simply 81 // observes that that class was aot-inited. The VM assumes that, if 82 // it were to run <clinit> again, it would get a semantically 83 // equivalent set of final field values, so it just adopts the 84 // existing field values (from AOT assembly) and skips the call to 85 // <clinit>. There may at that point be fixups performed by ad hoc 86 // code, if the VM recognizes a request in the library. 87 // 88 // It is true that this is not generally correct for all possible 89 // Java code. A <clinit> method might have a side effect beyond 90 // initializing the static fields. It might send an email somewhere 91 // noting the current time of day. In that case, such an email 92 // would have been sent during the AOT assembly phase, and the email 93 // would NOT be sent again during production. This is clearly NOT 94 // what a user would want, if this were a general purpose facility. 95 // But in fact it is only for certain well-behaved classes, which 96 // are known NOT to have such side effects. We know this because 97 // the optimization (of skipping <clinit> for aot-init classes) is 98 // only applied to classes fully defined by the JDK. 99 // 100 // (A day may come when we figure out how to gracefully extend this 101 // optimization to untrusted third parties, but it is not this day.) 102 // 103 // Manual selection 104 // ================ 105 // 106 // There are important cases where one aot-init class has a side 107 // effect on another aot-class, a side effect which is not captured 108 // in any static field value in either class. The simplest example 109 // is class A forces the initialization of class B. In that case, 110 // we need to aot-init either both classes or neither. From looking 111 // at the JDK state after AOT assembly is done, it is hard to tell 112 // that A "touched" B and B might escape our notice. Another common 113 // example is A copying a field value from B. We don't know where A 114 // got the value, but it would be wrong to re-initialize B at 115 // startup, while keeping the snapshot of the old B value in A. In 116 // general, if we aot-init A, we need to aot-init every class B that 117 // somehow contributed to A's initial state, and every class C that 118 // was somehow side-effected by A's initialization. We say that the 119 // aot-init of A is "init-coupled" to those of B and C. 120 // 121 // So there are init-coupled classes that cannot be automatically discovered. For 122 // example, DirectMethodHandle::IMPL_NAMES points to MethodHandles::IMPL_NAMES, 123 // but the MethodHandles class is not automatically marked because there are 124 // no archived instances of the MethodHandles type. 125 // 126 // If we aot-initialize DirectMethodHandle, but allow MethodHandles to be 127 // initialized at runtime, MethodHandles::IMPL_NAMES will get a different 128 // value than DirectMethodHandle::IMPL_NAMES. This *may or may not* be a problem, 129 // but to ensure compatibility, we should try to preserve the identity equality 130 // of these two fields. 131 // 132 // To do that, we add MethodHandles to the indy_specs[] table below. 133 // 134 // Luckily we do not need to be all-knowing in order to choose which 135 // items to add to that table. We have tools to help detect couplings. 136 // 137 // Automatic validation 138 // ==================== 139 // 140 // CDSHeapVerifier is used to detect potential problems with identity equality. 141 // 142 // A class B is assumed to be init-coupled to some aot-init class if 143 // B has a field which points to a live object X in the AOT heap. 144 // The live object X was created by some other class A which somehow 145 // used B's reference to X, perhaps with the help of an intermediate 146 // class Z. Or, B pulled the reference to X from some other class 147 // Y, and B obtained that reference from Y (or an intermediate Z). 148 // It is not certain how X got into the heap, nor whether B 149 // contributed it, but it is a good heuristic that B is init-coupled 150 // to X's class or some other aot-init class. In any case, B should 151 // be made an aot-init class as well, unless a manual inspection 152 // shows that would be a problem. If there is a problem, then the 153 // JDK code for B and/or X probably needs refactoring. If there is 154 // no problem, we add B to the list. Typically the same scan will 155 // find any other accomplices Y, Z, etc. One failure would be a 156 // class Q whose only initialization action is to scribble a special 157 // value into B, from which the value X is derived and then makes 158 // its way into the heap. In that case, the heuristic does not 159 // identify Q. It is (currently) a human responsibility, of JDK 160 // engineers, not to write such dirty JDK code, or to repair it if 161 // it crops up. Eventually we may have tools, or even a user mode 162 // with design rules and checks, that will vet our code base more 163 // automatically. 164 // 165 // To see how the tool detects the problem with MethodHandles::IMPL_NAMES: 166 // 167 // - Comment out all the lines in indy_specs[] except the {nullptr} line. 168 // - Rebuild the JDK 169 // 170 // Then run the following: 171 // java -XX:AOTMode=record -XX:AOTConfiguration=jc.aotconfig com.sun.tools.javac.Main 172 // java -XX:AOTMode=create -Xlog:aot -XX:AOTCache=jc.aot -XX:AOTConfiguration=jc.aotconfig 173 // 174 // You will see an error like this: 175 // 176 // Archive heap points to a static field that may hold a different value at runtime: 177 // Field: java/lang/invoke/MethodHandles::IMPL_NAMES 178 // Value: java.lang.invoke.MemberName$Factory 179 // {0x000000060e906ae8} - klass: 'java/lang/invoke/MemberName$Factory' - flags: 180 // 181 // - ---- fields (total size 2 words): 182 // --- trace begin --- 183 // [ 0] {0x000000060e8deeb0} java.lang.Class (java.lang.invoke.DirectMethodHandle::IMPL_NAMES) 184 // [ 1] {0x000000060e906ae8} java.lang.invoke.MemberName$Factory 185 // --- trace end --- 186 // 187 // Trouble-shooting 188 // ================ 189 // 190 // If you see a "static field that may hold a different value" error, it's probably 191 // because you've made some changes in the JDK core libraries (most likely 192 // java.lang.invoke). 193 // 194 // - Did you add a new static field to a class that could be referenced by 195 // cached object instances of MethodType, MethodHandle, etc? You may need 196 // to add that class to indy_specs[]. 197 // - Did you modify the <clinit> of the classes in java.lang.invoke such that 198 // a static field now points to an object that should not be cached (e.g., 199 // a native resource such as a file descriptior, or a Thread)? 200 // 201 // Note that these potential problems only occur when one class gets 202 // the aot-init treatment, AND another class is init-coupled to it, 203 // AND the coupling is not detected. Currently there are a number 204 // classes that get the aot-init treatment, in java.lang.invoke 205 // because of invokedynamic. They are few enough for now to be 206 // manually tracked. There may be more in the future. 207 208 { 209 if (ik == vmClasses::Object_klass()) { 210 // everybody's favorite super 211 return true; 212 } 213 } 214 215 if (CDSConfig::is_dumping_method_handles()) { 216 // The minimal list of @AOTSafeClassInitializer was created with the help of CDSHeapVerifier. 217 // Also, some $Holder classes are needed. E.g., Invokers.<clinit> explicitly 218 // initializes Invokers$Holder. Since Invokers.<clinit> won't be executed 219 // at runtime, we need to make sure Invokers$Holder is also aot-inited. 220 if (ik->has_aot_safe_initializer()) { 221 return true; 222 } 223 } 224 225 #ifdef ASSERT 226 if (ik == _aot_init_class) { 227 return true; 228 } 229 #endif 230 231 return false; 232 } 233 234 void AOTClassInitializer::call_runtime_setup(JavaThread* current, InstanceKlass* ik) { 235 assert(ik->has_aot_initialized_mirror(), "sanity"); 236 if (ik->is_runtime_setup_required()) { 237 if (log_is_enabled(Info, aot, init)) { 238 ResourceMark rm; 239 log_info(aot, init)("Calling %s::runtimeSetup()", ik->external_name()); 240 } 241 JavaValue result(T_VOID); 242 JavaCalls::call_static(&result, ik, 243 vmSymbols::runtimeSetup(), 244 vmSymbols::void_method_signature(), current); 245 if (current->has_pending_exception()) { 246 // We cannot continue, as we might have cached instances of ik in the heap, but propagating the 247 // exception would cause ik to be in an error state. 248 AOTLinkedClassBulkLoader::exit_on_exception(current); 249 } 250 } 251 } 252 253 // check_can_be_preinited() is quite costly, so we cache the results inside 254 // DumpTimeClassInfo::_can_be_preinited. See also AOTClassInitializer::reset_preinit_check(). 255 bool AOTClassInitializer::check_can_be_preinited(InstanceKlass* ik) { 256 ResourceMark rm; 257 258 if (!SystemDictionaryShared::is_builtin(ik)) { 259 log_info(cds, init)("cannot initialize %s (not built-in loader)", ik->external_name()); 260 return false; 261 } 262 263 InstanceKlass* super = ik->java_super(); 264 if (super != nullptr && !can_be_preinited_locked(super)) { 265 log_info(cds, init)("cannot initialize %s (super %s not initable)", ik->external_name(), super->external_name()); 266 return false; 267 } 268 269 Array<InstanceKlass*>* interfaces = ik->local_interfaces(); 270 for (int i = 0; i < interfaces->length(); i++) { 271 if (!can_be_preinited_locked(interfaces->at(i))) { 272 log_info(cds, init)("cannot initialize %s (interface %s not initable)", 273 ik->external_name(), interfaces->at(i)->external_name()); 274 return false; 275 } 276 } 277 278 if (HeapShared::is_lambda_form_klass(ik)) { 279 // We allow only these to have <clinit> or non-default static fields 280 return true; 281 } 282 283 if (ik->class_initializer() != nullptr) { 284 log_info(cds, init)("cannot initialize %s (has <clinit>)", ik->external_name()); 285 return false; 286 } 287 if (ik->is_initialized() && !has_default_static_fields(ik)) { 288 return false; 289 } 290 291 return true; 292 } 293 294 bool AOTClassInitializer::has_default_static_fields(InstanceKlass* ik) { 295 oop mirror = ik->java_mirror(); 296 297 for (JavaFieldStream fs(ik); !fs.done(); fs.next()) { 298 if (fs.access_flags().is_static()) { 299 fieldDescriptor& fd = fs.field_descriptor(); 300 int offset = fd.offset(); 301 bool is_default = true; 302 bool has_initval = fd.has_initial_value(); 303 switch (fd.field_type()) { 304 case T_OBJECT: 305 case T_ARRAY: 306 is_default = mirror->obj_field(offset) == nullptr; 307 break; 308 case T_BOOLEAN: 309 is_default = mirror->bool_field(offset) == (has_initval ? fd.int_initial_value() : 0); 310 break; 311 case T_BYTE: 312 is_default = mirror->byte_field(offset) == (has_initval ? fd.int_initial_value() : 0); 313 break; 314 case T_SHORT: 315 is_default = mirror->short_field(offset) == (has_initval ? fd.int_initial_value() : 0); 316 break; 317 case T_CHAR: 318 is_default = mirror->char_field(offset) == (has_initval ? fd.int_initial_value() : 0); 319 break; 320 case T_INT: 321 is_default = mirror->int_field(offset) == (has_initval ? fd.int_initial_value() : 0); 322 break; 323 case T_LONG: 324 is_default = mirror->long_field(offset) == (has_initval ? fd.long_initial_value() : 0); 325 break; 326 case T_FLOAT: 327 is_default = mirror->float_field(offset) == (has_initval ? fd.float_initial_value() : 0); 328 break; 329 case T_DOUBLE: 330 is_default = mirror->double_field(offset) == (has_initval ? fd.double_initial_value() : 0); 331 break; 332 default: 333 ShouldNotReachHere(); 334 } 335 336 if (!is_default) { 337 log_info(cds, init)("cannot initialize %s (static field %s has non-default value)", 338 ik->external_name(), fd.name()->as_C_string()); 339 return false; 340 } 341 } 342 } 343 344 return true; 345 } 346 347 bool AOTClassInitializer::can_be_preinited(InstanceKlass* ik) { 348 MutexLocker ml(DumpTimeTable_lock, Mutex::_no_safepoint_check_flag); 349 return can_be_preinited_locked(ik); 350 } 351 352 bool AOTClassInitializer::can_be_preinited_locked(InstanceKlass* ik) { 353 if (!CDSConfig::is_initing_classes_at_dump_time()) { 354 return false; 355 } 356 357 assert_lock_strong(DumpTimeTable_lock); 358 DumpTimeClassInfo* info = SystemDictionaryShared::get_info_locked(ik); 359 if (!info->has_done_preinit_check()) { 360 info->set_can_be_preinited(AOTClassInitializer::check_can_be_preinited(ik)); 361 } 362 return info->can_be_preinited(); 363 } 364 365 // Initialize a class at dump time, if possible. 366 void AOTClassInitializer::maybe_preinit_class(InstanceKlass* ik, TRAPS) { 367 #if 0 // FIXME -- leyden+JEP483 merge 368 if (!ik->is_initialized() && AOTClassInitializer::can_be_preinited(ik)) { 369 if (log_is_enabled(Info, cds, init)) { 370 ResourceMark rm; 371 log_info(cds, init)("preinitializing %s", ik->external_name()); 372 } 373 ik->initialize(CHECK); 374 } 375 #endif 376 } 377 378 #ifdef ASSERT 379 void AOTClassInitializer::init_test_class(TRAPS) { 380 // -XX:AOTInitTestClass is used in regression tests for adding additional AOT-initialized classes 381 // and heap objects into the AOT cache. The tests must be carefully written to avoid including 382 // any classes that cannot be AOT-initialized. 383 // 384 // -XX:AOTInitTestClass is NOT a general mechanism for including user-defined objects into 385 // the AOT cache. Therefore, this option is NOT available in product JVM. 386 if (AOTInitTestClass != nullptr && CDSConfig::is_initing_classes_at_dump_time()) { 387 log_info(aot)("Debug build only: force initialization of AOTInitTestClass %s", AOTInitTestClass); 388 TempNewSymbol class_name = SymbolTable::new_symbol(AOTInitTestClass); 389 Handle app_loader(THREAD, SystemDictionary::java_system_loader()); 390 Klass* k = SystemDictionary::resolve_or_null(class_name, app_loader, CHECK); 391 if (k == nullptr) { 392 vm_exit_during_initialization("AOTInitTestClass not found", AOTInitTestClass); 393 } 394 if (!k->is_instance_klass()) { 395 vm_exit_during_initialization("Invalid name for AOTInitTestClass", AOTInitTestClass); 396 } 397 398 _aot_init_class = InstanceKlass::cast(k); 399 _aot_init_class->initialize(CHECK); 400 } 401 } 402 403 bool AOTClassInitializer::has_test_class() { 404 return _aot_init_class != nullptr; 405 } 406 #endif