/
githubmirror
/
panama-vector
Обзор
Документация
Войти
/
githubmirror
/
panama-vector
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
src/hotspot/share/cds/dumpTimeClassInfo.hpp
288 строк
10 KB
Ioi Lam
8378749: Early GC crash with unresolved AOT FMG subgraph classes
23 мар 2026, 07:35
23 мар 2026, 07:35
a6f59ba
Код
Авторство
О чём код?
/* * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. * */ #ifndef SHARE_CDS_DUMPTIMECLASSINFO_HPP #define SHARE_CDS_DUMPTIMECLASSINFO_HPP #include "cds/aotMetaspace.hpp" #include "cds/archiveBuilder.hpp" #include "cds/archiveUtils.hpp" #include "cds/cdsConfig.hpp" #include "classfile/compactHashtable.hpp" #include "memory/metaspaceClosure.hpp" #include "oops/instanceKlass.hpp" #include "prims/jvmtiExport.hpp" #include "utilities/growableArray.hpp" class Method; class Symbol; class DumpTimeClassInfo: public CHeapObj<mtClass> { bool _excluded; bool _is_aot_tooling_class; bool _has_checked_exclusion; class DTLoaderConstraint { Symbol* _name; char _loader_type1; char _loader_type2; public: DTLoaderConstraint() : _name(nullptr), _loader_type1('0'), _loader_type2('0') {} DTLoaderConstraint(Symbol* name, char l1, char l2) : _name(name), _loader_type1(l1), _loader_type2(l2) { Symbol::maybe_increment_refcount(_name); } DTLoaderConstraint(const DTLoaderConstraint& src) { _name = src._name; _loader_type1 = src._loader_type1; _loader_type2 = src._loader_type2; Symbol::maybe_increment_refcount(_name); } DTLoaderConstraint& operator=(DTLoaderConstraint src) { swap(_name, src._name); // c++ copy-and-swap idiom _loader_type1 = src._loader_type1; _loader_type2 = src._loader_type2; return *this; } ~DTLoaderConstraint() { Symbol::maybe_decrement_refcount(_name); } bool equals(const DTLoaderConstraint& t) { return t._name == _name && ((t._loader_type1 == _loader_type1 && t._loader_type2 == _loader_type2) || (t._loader_type2 == _loader_type1 && t._loader_type1 == _loader_type2)); } void metaspace_pointers_do(MetaspaceClosure* it) { it->push(&_name); } Symbol* name() { return _name; } char loader_type1() { return _loader_type1; } char loader_type2() { return _loader_type2; } }; class DTVerifierConstraint { Symbol* _name; Symbol* _from_name; public: DTVerifierConstraint() : _name(nullptr), _from_name(nullptr) {} DTVerifierConstraint(Symbol* n, Symbol* fn = nullptr) : _name(n), _from_name(fn) { Symbol::maybe_increment_refcount(_name); Symbol::maybe_increment_refcount(_from_name); } DTVerifierConstraint(const DTVerifierConstraint& src) { _name = src._name; _from_name = src._from_name; Symbol::maybe_increment_refcount(_name); Symbol::maybe_increment_refcount(_from_name); } DTVerifierConstraint& operator=(DTVerifierConstraint src) { swap(_name, src._name); // c++ copy-and-swap idiom swap(_from_name, src._from_name); // c++ copy-and-swap idiom return *this; } ~DTVerifierConstraint() { Symbol::maybe_decrement_refcount(_name); Symbol::maybe_decrement_refcount(_from_name); } bool equals(Symbol* n, Symbol* fn) { return (_name == n) && (_from_name == fn); } void metaspace_pointers_do(MetaspaceClosure* it) { it->push(&_name); it->push(&_from_name); } Symbol* name() { return _name; } Symbol* from_name() { return _from_name; } }; public: InstanceKlass* _klass; InstanceKlass* _nest_host; bool _failed_verification; bool _is_registered_lambda_proxy; int _id; int _clsfile_size; int _clsfile_crc32; GrowableArray<DTVerifierConstraint>* _verifier_constraints; GrowableArray<char>* _verifier_constraint_flags; GrowableArray<DTLoaderConstraint>* _loader_constraints; GrowableArray<int>* _enum_klass_static_fields; DumpTimeClassInfo() { _klass = nullptr; _nest_host = nullptr; _failed_verification = false; _is_registered_lambda_proxy = false; _has_checked_exclusion = false; _id = -1; _clsfile_size = -1; _clsfile_crc32 = -1; _excluded = false; _is_aot_tooling_class = false; _verifier_constraints = nullptr; _verifier_constraint_flags = nullptr; _loader_constraints = nullptr; _enum_klass_static_fields = nullptr; } DumpTimeClassInfo& operator=(const DumpTimeClassInfo&) = delete; ~DumpTimeClassInfo(); // For old verifier: only name is saved; all other fields are null/false. void add_verification_constraint(Symbol* name, Symbol* from_name = nullptr, bool from_field_is_protected = false, bool from_is_array = false, bool from_is_object = false); void record_linking_constraint(Symbol* name, Handle loader1, Handle loader2); void add_enum_klass_static_field(int archived_heap_root_index); int enum_klass_static_field(int which_field); bool is_builtin(); private: template <typename T> static int array_length_or_zero(GrowableArray<T>* array) { if (array == nullptr) { return 0; } else { return array->length(); } } public: int num_verifier_constraints() const { return array_length_or_zero(_verifier_constraint_flags); } Symbol* verifier_constraint_name_at(int i) const { return _verifier_constraints->at(i).name(); } Symbol* verifier_constraint_from_name_at(int i) const { return _verifier_constraints->at(i).from_name(); } int num_loader_constraints() const { return array_length_or_zero(_loader_constraints); } int num_enum_klass_static_fields() const { return array_length_or_zero(_enum_klass_static_fields); } void metaspace_pointers_do(MetaspaceClosure* it) { it->push(&_klass); it->push(&_nest_host); if (_verifier_constraints != nullptr) { for (int i = 0; i < _verifier_constraints->length(); i++) { _verifier_constraints->adr_at(i)->metaspace_pointers_do(it); } } if (_loader_constraints != nullptr) { for (int i = 0; i < _loader_constraints->length(); i++) { _loader_constraints->adr_at(i)->metaspace_pointers_do(it); } } } bool is_excluded() { return _excluded || _failed_verification; } bool is_aot_tooling_class() { return _is_aot_tooling_class; } void set_is_aot_tooling_class() { _is_aot_tooling_class = true; } // simple accessors void set_excluded() { _excluded = true; } bool has_checked_exclusion() const { return _has_checked_exclusion; } void set_has_checked_exclusion() { _has_checked_exclusion = true; } bool failed_verification() const { return _failed_verification; } void set_failed_verification() { _failed_verification = true; } InstanceKlass* nest_host() const { return _nest_host; } void set_nest_host(InstanceKlass* nest_host) { _nest_host = nest_host; } size_t runtime_info_bytesize() const; }; template <typename T> inline unsigned DumpTimeSharedClassTable_hash(T* const& k) { if (CDSConfig::is_dumping_static_archive()) { // Deterministic archive contents uintx delta = k->name() - AOTMetaspace::symbol_rs_base(); return primitive_hash<uintx>(delta); } else { // Deterministic archive is not possible because classes can be loaded // in multiple threads. return primitive_hash<T*>(k); } } using DumpTimeSharedClassTableBaseType = HashTable< InstanceKlass*, DumpTimeClassInfo, 15889, // prime number AnyObj::C_HEAP, mtClassShared, &DumpTimeSharedClassTable_hash>; class DumpTimeSharedClassTable: public DumpTimeSharedClassTableBaseType { int _builtin_count; int _unregistered_count; public: DumpTimeSharedClassTable() { _builtin_count = 0; _unregistered_count = 0; } DumpTimeClassInfo* allocate_info(InstanceKlass* k); DumpTimeClassInfo* get_info(InstanceKlass* k); void inc_builtin_count() { _builtin_count++; } void inc_unregistered_count() { _unregistered_count++; } void update_counts(); int count_of(bool is_builtin) const { if (is_builtin) { return _builtin_count; } else { return _unregistered_count; } } template<class ITER> void iterate_all_live_classes(ITER* iter) const; template<typename Function> void iterate_all_live_classes(Function function) const; private: // It's unsafe to iterate on classes whose loader is dead. // Declare these private and don't implement them. This forces users of // DumpTimeSharedClassTable to use the iterate_all_live_classes() methods // instead. template<class ITER> void iterate(ITER* iter) const; template<typename Function> void iterate(Function function) const; template<typename Function> void iterate_all(Function function) const; }; #endif // SHARE_CDS_DUMPTIMECLASSINFO_HPP