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