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