< prev index next >

src/hotspot/share/cds/aotClassInitializer.cpp

Print this page

  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 {

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 





























































































































  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 "precompiled.hpp"
 26 #include "cds/aotClassInitializer.hpp"
 27 #include "cds/archiveBuilder.hpp"
 28 #include "cds/cdsConfig.hpp"
 29 #include "dumpTimeClassInfo.inline.hpp"
 30 #include "cds/heapShared.hpp"
 31 #include "classfile/systemDictionaryShared.hpp"
 32 #include "classfile/vmSymbols.hpp"
 33 #include "memory/resourceArea.hpp"
 34 #include "oops/fieldStreams.inline.hpp"
 35 #include "oops/instanceKlass.inline.hpp"
 36 #include "oops/symbol.hpp"
 37 #include "runtime/fieldDescriptor.inline.hpp"
 38 #include "runtime/javaCalls.hpp"
 39 #include "runtime/mutexLocker.hpp"
 40 
 41 // Detector for class names we wish to handle specially.
 42 // It is either an exact string match or a string prefix match.
 43 class AOTClassInitializer::AllowedSpec {
 44   const char* _class_name;
 45   bool _is_prefix;
 46   int _len;
 47 public:
 48   AllowedSpec(const char* class_name, bool is_prefix = false)
 49     : _class_name(class_name), _is_prefix(is_prefix)
 50   {
 51     _len = (class_name == nullptr) ? 0 : (int)strlen(class_name);
 52   }
 53   const char* class_name() { return _class_name; }
 54 
 55   bool matches(Symbol* name, int len) {
 56     assert(_class_name != nullptr, "caller resp.");
 57     if (_is_prefix) {
 58       return len >= _len && name->starts_with(_class_name);
 59     } else {

324     // MethodHandleStatics is an example of a class that must NOT get the aot-init treatment,
325     // because of its strong reliance on (a) final fields which are (b) environmentally determined.
326     //{"java/lang/invoke/InvokerBytecodeGenerator"},
327 
328       {nullptr}
329     };
330     if (is_allowed(indy_specs, ik)) {
331       return true;
332     }
333   }
334 
335   return false;
336 }
337 
338 // TODO: currently we have a hard-coded list. We should turn this into
339 // an annotation: @jdk.internal.vm.annotation.RuntimeSetupRequired
340 // See JDK-8342481.
341 bool AOTClassInitializer::is_runtime_setup_required(InstanceKlass* ik) {
342   return ik == vmClasses::Class_klass() ||
343          ik == vmClasses::internal_Unsafe_klass() ||
344          ik == vmClasses::ConcurrentHashMap_klass() ||
345          ik->name()->equals("java/net/URI") ||
346          ik->name()->equals("java/lang/module/ModuleDescriptor");
347 }
348 
349 void AOTClassInitializer::call_runtime_setup(JavaThread* current, InstanceKlass* ik) {
350   assert(ik->has_aot_initialized_mirror(), "sanity");
351   if (ik->is_runtime_setup_required()) {
352     if (log_is_enabled(Info, cds, init)) {
353       ResourceMark rm;
354       log_info(cds, init)("Calling %s::runtimeSetup()", ik->external_name());
355     }
356     JavaValue result(T_VOID);
357     JavaCalls::call_static(&result, ik,
358                            vmSymbols::runtimeSetup(),
359                            vmSymbols::void_method_signature(), current);
360     if (current->has_pending_exception()) {
361       // We cannot continue, as we might have cached instances of ik in the heap, but propagating the
362       // exception would cause ik to be in an error state.
363       AOTLinkedClassBulkLoader::exit_on_exception(current);
364     }
365   }
366 }
367 
368 // check_can_be_preinited() is quite costly, so we cache the results inside
369 // DumpTimeClassInfo::_can_be_preinited. See also AOTClassInitializer::reset_preinit_check().
370 bool AOTClassInitializer::check_can_be_preinited(InstanceKlass* ik) {
371   ResourceMark rm;
372 
373   if (!SystemDictionaryShared::is_builtin(ik)) {
374     log_info(cds, init)("cannot initialize %s (not built-in loader)", ik->external_name());
375     return false;
376   }
377 
378   InstanceKlass* super = ik->java_super();
379   if (super != nullptr && !can_be_preinited_locked(super)) {
380     log_info(cds, init)("cannot initialize %s (super %s not initable)", ik->external_name(), super->external_name());
381     return false;
382   }
383 
384   Array<InstanceKlass*>* interfaces = ik->local_interfaces();
385   for (int i = 0; i < interfaces->length(); i++) {
386     if (!can_be_preinited_locked(interfaces->at(i))) {
387       log_info(cds, init)("cannot initialize %s (interface %s not initable)",
388                           ik->external_name(), interfaces->at(i)->external_name());
389       return false;
390     }
391   }
392 
393   if (HeapShared::is_lambda_form_klass(ik)) {
394     // We allow only these to have <clinit> or non-default static fields
395     return true;
396   }
397 
398   if (ik->class_initializer() != nullptr) {
399     log_info(cds, init)("cannot initialize %s (has <clinit>)", ik->external_name());
400     return false;
401   }
402   if (ik->is_initialized() && !has_default_static_fields(ik)) {
403     return false;
404   }
405 
406   return true;
407 }
408 
409 bool AOTClassInitializer::has_default_static_fields(InstanceKlass* ik) {
410   oop mirror = ik->java_mirror();
411 
412   for (JavaFieldStream fs(ik); !fs.done(); fs.next()) {
413     if (fs.access_flags().is_static()) {
414       fieldDescriptor& fd = fs.field_descriptor();
415       int offset = fd.offset();
416       bool is_default = true;
417       bool has_initval = fd.has_initial_value();
418       switch (fd.field_type()) {
419       case T_OBJECT:
420       case T_ARRAY:
421         is_default = mirror->obj_field(offset) == nullptr;
422         break;
423       case T_BOOLEAN:
424         is_default = mirror->bool_field(offset) == (has_initval ? fd.int_initial_value() : 0);
425         break;
426       case T_BYTE:
427         is_default = mirror->byte_field(offset) == (has_initval ? fd.int_initial_value() : 0);
428         break;
429       case T_SHORT:
430         is_default = mirror->short_field(offset) == (has_initval ? fd.int_initial_value() : 0);
431         break;
432       case T_CHAR:
433         is_default = mirror->char_field(offset) == (has_initval ? fd.int_initial_value() : 0);
434         break;
435       case T_INT:
436         is_default = mirror->int_field(offset) == (has_initval ? fd.int_initial_value() : 0);
437         break;
438       case T_LONG:
439         is_default = mirror->long_field(offset) == (has_initval ? fd.long_initial_value() : 0);
440         break;
441       case T_FLOAT:
442         is_default = mirror->float_field(offset) == (has_initval ? fd.float_initial_value() : 0);
443         break;
444       case T_DOUBLE:
445         is_default = mirror->double_field(offset) == (has_initval ? fd.double_initial_value() : 0);
446         break;
447       default:
448         ShouldNotReachHere();
449       }
450 
451       if (!is_default) {
452         log_info(cds, init)("cannot initialize %s (static field %s has non-default value)",
453                             ik->external_name(), fd.name()->as_C_string());
454         return false;
455       }
456     }
457   }
458 
459   return true;
460 }
461 
462 bool AOTClassInitializer::can_be_preinited(InstanceKlass* ik) {
463   MutexLocker ml(DumpTimeTable_lock, Mutex::_no_safepoint_check_flag);
464   return can_be_preinited_locked(ik);
465 }
466 
467 bool AOTClassInitializer::can_be_preinited_locked(InstanceKlass* ik) {
468   if (!CDSConfig::is_initing_classes_at_dump_time()) {
469     return false;
470   }
471 
472   assert_lock_strong(DumpTimeTable_lock);
473   DumpTimeClassInfo* info = SystemDictionaryShared::get_info_locked(ik);
474   if (!info->has_done_preinit_check()) {
475     info->set_can_be_preinited(AOTClassInitializer::check_can_be_preinited(ik));
476   }
477   return info->can_be_preinited();
478 }
479 
480 // Initialize a class at dump time, if possible.
481 void AOTClassInitializer::maybe_preinit_class(InstanceKlass* ik, TRAPS) {
482 #if 0 // FIXME -- leyden+JEP483 merge
483   if (!ik->is_initialized() && AOTClassInitializer::can_be_preinited(ik)) {
484     if (log_is_enabled(Info, cds, init)) {
485       ResourceMark rm;
486       log_info(cds, init)("preinitializing %s", ik->external_name());
487     }
488     ik->initialize(CHECK);
489   }
490 #endif
491 }
< prev index next >