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