< prev index next >

src/hotspot/share/memory/metaspace.hpp

Print this page
rev 60538 : imported patch jep387-all.patch

*** 26,102 **** #include "memory/allocation.hpp" #include "memory/memRegion.hpp" #include "memory/metaspaceChunkFreeListSummary.hpp" #include "memory/virtualspace.hpp" - #include "memory/metaspace/metaspaceSizesSnapshot.hpp" #include "runtime/globals.hpp" #include "utilities/exceptions.hpp" ! ! // Metaspace ! // ! // Metaspaces are Arenas for the VM's metadata. ! // They are allocated one per class loader object, and one for the null ! // bootstrap class loader ! // ! // block X ---+ +-------------------+ ! // | | Virtualspace | ! // | | | ! // | | | ! // | |-------------------| ! // | || Chunk | ! // | || | ! // | ||---------- | ! // +------>||| block 0 | | ! // ||---------- | ! // ||| block 1 | | ! // ||---------- | ! // || | ! // |-------------------| ! // | | ! // | | ! // +-------------------+ ! // class ClassLoaderData; class MetaspaceTracer; class Mutex; class outputStream; - class CollectedHeap; - namespace metaspace { ! class ChunkManager; ! class ClassLoaderMetaspaceStatistics; ! class Metablock; ! class Metachunk; ! class PrintCLDMetaspaceInfoClosure; ! class SpaceManager; ! class VirtualSpaceList; ! class VirtualSpaceNode; } ! // Metaspaces each have a SpaceManager and allocations ! // are done by the SpaceManager. Allocations are done ! // out of the current Metachunk. When the current Metachunk ! // is exhausted, the SpaceManager gets a new one from ! // the current VirtualSpace. When the VirtualSpace is exhausted ! // the SpaceManager gets a new one. The SpaceManager ! // also manages freelists of available Chunks. ! // ! // Currently the space manager maintains the list of ! // virtual spaces and the list of chunks in use. Its ! // allocate() method returns a block for use as a ! // quantum of metadata. // Namespace for important central static functions // (auxiliary stuff goes into MetaspaceUtils) class Metaspace : public AllStatic { friend class MetaspaceShared; ! public: enum MetadataType { ClassType, NonClassType, MetadataTypeCount }; --- 26,60 ---- #include "memory/allocation.hpp" #include "memory/memRegion.hpp" #include "memory/metaspaceChunkFreeListSummary.hpp" #include "memory/virtualspace.hpp" #include "runtime/globals.hpp" #include "utilities/exceptions.hpp" ! #include "utilities/globalDefinitions.hpp" class ClassLoaderData; + class MetaspaceShared; class MetaspaceTracer; class Mutex; class outputStream; namespace metaspace { ! class MetaspaceArena; ! class MetaspaceSizesSnapshot; ! struct clms_stats_t; } ! ////////////////// Metaspace /////////////////////// // Namespace for important central static functions // (auxiliary stuff goes into MetaspaceUtils) class Metaspace : public AllStatic { friend class MetaspaceShared; ! public: enum MetadataType { ClassType, NonClassType, MetadataTypeCount };
*** 107,169 **** ClassMirrorHolderMetaspaceType = BootMetaspaceType + 1, ReflectionMetaspaceType = ClassMirrorHolderMetaspaceType + 1, MetaspaceTypeCount }; ! private: ! ! // Align up the word size to the allocation word size ! static size_t align_word_size_up(size_t); ! ! // Aligned size of the metaspace. ! static size_t _compressed_class_space_size; ! ! static size_t compressed_class_space_size() { ! return _compressed_class_space_size; ! } ! ! static void set_compressed_class_space_size(size_t size) { ! _compressed_class_space_size = size; ! } ! ! static size_t _first_chunk_word_size; ! static size_t _first_class_chunk_word_size; - static size_t _commit_alignment; - static size_t _reserve_alignment; DEBUG_ONLY(static bool _frozen;) - // Virtual Space lists for both classes and other metadata - static metaspace::VirtualSpaceList* _space_list; - static metaspace::VirtualSpaceList* _class_space_list; - - static metaspace::ChunkManager* _chunk_manager_metadata; - static metaspace::ChunkManager* _chunk_manager_class; - static const MetaspaceTracer* _tracer; static bool _initialized; ! public: ! static metaspace::VirtualSpaceList* space_list() { return _space_list; } ! static metaspace::VirtualSpaceList* class_space_list() { return _class_space_list; } ! static metaspace::VirtualSpaceList* get_space_list(MetadataType mdtype) { ! assert(mdtype != MetadataTypeCount, "MetadaTypeCount can't be used as mdtype"); ! return mdtype == ClassType ? class_space_list() : space_list(); ! } ! ! static metaspace::ChunkManager* chunk_manager_metadata() { return _chunk_manager_metadata; } ! static metaspace::ChunkManager* chunk_manager_class() { return _chunk_manager_class; } ! static metaspace::ChunkManager* get_chunk_manager(MetadataType mdtype) { ! assert(mdtype != MetadataTypeCount, "MetadaTypeCount can't be used as mdtype"); ! return mdtype == ClassType ? chunk_manager_class() : chunk_manager_metadata(); ! } ! ! // convenience function ! static metaspace::ChunkManager* get_chunk_manager(bool is_class) { ! return is_class ? chunk_manager_class() : chunk_manager_metadata(); ! } static const MetaspaceTracer* tracer() { return _tracer; } static void freeze() { assert(DumpSharedSpaces, "sanity"); DEBUG_ONLY(_frozen = true;) --- 65,83 ---- ClassMirrorHolderMetaspaceType = BootMetaspaceType + 1, ReflectionMetaspaceType = ClassMirrorHolderMetaspaceType + 1, MetaspaceTypeCount }; ! private: DEBUG_ONLY(static bool _frozen;) static const MetaspaceTracer* _tracer; static bool _initialized; ! public: static const MetaspaceTracer* tracer() { return _tracer; } static void freeze() { assert(DumpSharedSpaces, "sanity"); DEBUG_ONLY(_frozen = true;)
*** 186,447 **** // Given a prereserved space, use that to set up the compressed class space list. static void initialize_class_space(ReservedSpace rs); // Returns true if class space has been setup (initialize_class_space). ! static bool class_space_is_initialized() { return _class_space_list != NULL; } #endif public: static void ergo_initialize(); static void global_initialize(); static void post_initialize(); ! static void verify_global_initialization(); ! ! static size_t first_chunk_word_size() { return _first_chunk_word_size; } ! static size_t first_class_chunk_word_size() { return _first_class_chunk_word_size; } ! static size_t reserve_alignment() { return _reserve_alignment; } ! static size_t reserve_alignment_words() { return _reserve_alignment / BytesPerWord; } ! static size_t commit_alignment() { return _commit_alignment; } ! static size_t commit_alignment_words() { return _commit_alignment / BytesPerWord; } static MetaWord* allocate(ClassLoaderData* loader_data, size_t word_size, MetaspaceObj::Type type, TRAPS); static bool contains(const void* ptr); static bool contains_non_shared(const void* ptr); // Free empty virtualspaces - static void purge(MetadataType mdtype); static void purge(); static void report_metadata_oome(ClassLoaderData* loader_data, size_t word_size, ! MetaspaceObj::Type type, MetadataType mdtype, TRAPS); ! ! static const char* metadata_type_name(Metaspace::MetadataType mdtype); static void print_compressed_class_space(outputStream* st) NOT_LP64({}); // Return TRUE only if UseCompressedClassPointers is True. static bool using_class_space() { return NOT_LP64(false) LP64_ONLY(UseCompressedClassPointers); } ! static bool is_class_space_allocation(MetadataType mdType) { ! return mdType == ClassType && using_class_space(); ! } ! ! static bool initialized() { return _initialized; } }; ! // Manages the metaspace portion belonging to a class loader class ClassLoaderMetaspace : public CHeapObj<mtClass> { - friend class CollectedHeap; // For expand_and_allocate() - friend class ZCollectedHeap; // For expand_and_allocate() - friend class ShenandoahHeap; // For expand_and_allocate() - friend class Metaspace; - friend class MetaspaceUtils; - friend class metaspace::PrintCLDMetaspaceInfoClosure; - friend class VM_CollectForMetadataAllocation; // For expand_and_allocate() ! private: ! ! void initialize(Mutex* lock, Metaspace::MetaspaceType type); ! ! // Initialize the first chunk for a Metaspace. Used for ! // special cases such as the boot class loader, reflection ! // class loader and hidden class loader. ! void initialize_first_chunk(Metaspace::MetaspaceType type, Metaspace::MetadataType mdtype); ! metaspace::Metachunk* get_initialization_chunk(Metaspace::MetaspaceType type, Metaspace::MetadataType mdtype); const Metaspace::MetaspaceType _space_type; - Mutex* const _lock; - metaspace::SpaceManager* _vsm; - metaspace::SpaceManager* _class_vsm; ! metaspace::SpaceManager* vsm() const { return _vsm; } ! metaspace::SpaceManager* class_vsm() const { return _class_vsm; } ! metaspace::SpaceManager* get_space_manager(Metaspace::MetadataType mdtype) { ! assert(mdtype != Metaspace::MetadataTypeCount, "MetadaTypeCount can't be used as mdtype"); ! return mdtype == Metaspace::ClassType ? class_vsm() : vsm(); ! } Mutex* lock() const { return _lock; } ! MetaWord* expand_and_allocate(size_t size, Metaspace::MetadataType mdtype); ! ! size_t class_chunk_size(size_t word_size); ! // Adds to the given statistic object. Must be locked with CLD metaspace lock. ! void add_to_statistics_locked(metaspace::ClassLoaderMetaspaceStatistics* out) const; ! Metaspace::MetaspaceType space_type() const { return _space_type; } - public: - - ClassLoaderMetaspace(Mutex* lock, Metaspace::MetaspaceType type); ~ClassLoaderMetaspace(); ! // Allocate space for metadata of type mdtype. This is space ! // within a Metachunk and is used by ! // allocate(ClassLoaderData*, size_t, bool, MetadataType, TRAPS) ! MetaWord* allocate(size_t word_size, Metaspace::MetadataType mdtype); ! ! size_t allocated_blocks_bytes() const; ! size_t allocated_chunks_bytes() const; ! ! void deallocate(MetaWord* ptr, size_t byte_size, bool is_class); ! ! void print_on(outputStream* st) const; ! // Debugging support ! void verify(); ! ! // Adds to the given statistic object. Will lock with CLD metaspace lock. ! void add_to_statistics(metaspace::ClassLoaderMetaspaceStatistics* out) const; ! ! }; // ClassLoaderMetaspace ! ! class MetaspaceUtils : AllStatic { ! // Spacemanager updates running counters. ! friend class metaspace::SpaceManager; ! // Special access for error reporting (checks without locks). ! friend class oopDesc; ! friend class Klass; ! ! // Running counters for statistics concerning in-use chunks. ! // Note: capacity = used + free + waste + overhead. Note that we do not ! // count free and waste. Their sum can be deduces from the three other values. ! // For more details, one should call print_report() from within a safe point. ! static size_t _capacity_words [Metaspace:: MetadataTypeCount]; ! static size_t _overhead_words [Metaspace:: MetadataTypeCount]; ! static volatile size_t _used_words [Metaspace:: MetadataTypeCount]; ! ! // Atomically decrement or increment in-use statistic counters ! static void dec_capacity(Metaspace::MetadataType mdtype, size_t words); ! static void inc_capacity(Metaspace::MetadataType mdtype, size_t words); ! static void dec_used(Metaspace::MetadataType mdtype, size_t words); ! static void inc_used(Metaspace::MetadataType mdtype, size_t words); ! static void dec_overhead(Metaspace::MetadataType mdtype, size_t words); ! static void inc_overhead(Metaspace::MetadataType mdtype, size_t words); ! ! ! // Getters for the in-use counters. ! static size_t capacity_words(Metaspace::MetadataType mdtype) { return _capacity_words[mdtype]; } ! static size_t used_words(Metaspace::MetadataType mdtype) { return _used_words[mdtype]; } ! static size_t overhead_words(Metaspace::MetadataType mdtype) { return _overhead_words[mdtype]; } ! static size_t free_chunks_total_words(Metaspace::MetadataType mdtype); ! // Helper for print_xx_report. ! static void print_vs(outputStream* out, size_t scale); ! public: ! // Collect used metaspace statistics. This involves walking the CLDG. The resulting ! // output will be the accumulated values for all live metaspaces. ! // Note: method does not do any locking. ! static void collect_statistics(metaspace::ClassLoaderMetaspaceStatistics* out); ! ! // Used by MetaspaceCounters ! static size_t free_chunks_total_words(); ! static size_t free_chunks_total_bytes(); ! static size_t free_chunks_total_bytes(Metaspace::MetadataType mdtype); ! ! static size_t capacity_words() { ! return capacity_words(Metaspace::NonClassType) + ! capacity_words(Metaspace::ClassType); ! } ! static size_t capacity_bytes(Metaspace::MetadataType mdtype) { ! return capacity_words(mdtype) * BytesPerWord; ! } ! static size_t capacity_bytes() { ! return capacity_words() * BytesPerWord; ! } ! static size_t used_words() { ! return used_words(Metaspace::NonClassType) + ! used_words(Metaspace::ClassType); ! } ! static size_t used_bytes(Metaspace::MetadataType mdtype) { ! return used_words(mdtype) * BytesPerWord; ! } ! static size_t used_bytes() { ! return used_words() * BytesPerWord; ! } - // Space committed but yet unclaimed by any class loader. - static size_t free_in_vs_bytes(); - static size_t free_in_vs_bytes(Metaspace::MetadataType mdtype); - - static size_t reserved_bytes(Metaspace::MetadataType mdtype); - static size_t reserved_bytes() { - return reserved_bytes(Metaspace::ClassType) + - reserved_bytes(Metaspace::NonClassType); - } ! static size_t committed_bytes(Metaspace::MetadataType mdtype); ! static size_t committed_bytes() { ! return committed_bytes(Metaspace::ClassType) + ! committed_bytes(Metaspace::NonClassType); ! } ! static size_t min_chunk_size_words(); ! // Flags for print_report(). ! enum ReportFlag { ! // Show usage by class loader. ! rf_show_loaders = (1 << 0), ! // Breaks report down by chunk type (small, medium, ...). ! rf_break_down_by_chunktype = (1 << 1), ! // Breaks report down by space type (hidden, reflection, ...). ! rf_break_down_by_spacetype = (1 << 2), ! // Print details about the underlying virtual spaces. ! rf_show_vslist = (1 << 3), ! // Print metaspace map. ! rf_show_vsmap = (1 << 4), ! // If show_loaders: show loaded classes for each loader. ! rf_show_classes = (1 << 5) }; ! // This will print out a basic metaspace usage report but ! // unlike print_report() is guaranteed not to lock or to walk the CLDG. ! static void print_basic_report(outputStream* st, size_t scale); ! ! // Prints a report about the current metaspace state. ! // Optional parts can be enabled via flags. ! // Function will walk the CLDG and will lock the expand lock; if that is not ! // convenient, use print_basic_report() instead. ! static void print_report(outputStream* out, size_t scale = 0, int flags = 0); ! ! static bool has_chunk_free_list(Metaspace::MetadataType mdtype); ! static MetaspaceChunkFreeListSummary chunk_free_list_summary(Metaspace::MetadataType mdtype); ! ! // Log change in used metadata. ! static void print_metaspace_change(const metaspace::MetaspaceSizesSnapshot& pre_meta_values); ! static void print_on(outputStream * out); ! ! // Prints an ASCII representation of the given space. ! static void print_metaspace_map(outputStream* out, Metaspace::MetadataType mdtype); ! ! static void dump(outputStream* out); ! static void verify_free_chunks(); ! // Check internal counters (capacity, used). ! static void verify_metrics(); }; ! // Metaspace are deallocated when their class loader are GC'ed. ! // This class implements a policy for inducing GC's to recover ! // Metaspaces. ! ! class MetaspaceGC : AllStatic { // The current high-water-mark for inducing a GC. // When committed memory of all metaspaces reaches this value, // a GC is induced and the value is increased. Size is in bytes. static volatile size_t _capacity_until_GC; --- 100,261 ---- // Given a prereserved space, use that to set up the compressed class space list. static void initialize_class_space(ReservedSpace rs); // Returns true if class space has been setup (initialize_class_space). ! static bool class_space_is_initialized(); #endif public: static void ergo_initialize(); static void global_initialize(); static void post_initialize(); ! // Alignment, in bytes, of metaspace mappings ! static size_t reserve_alignment() { return reserve_alignment_words() * BytesPerWord; } ! // Alignment, in words, of metaspace mappings ! static size_t reserve_alignment_words(); ! ! // The granularity at which Metaspace is committed and uncommitted. ! // (Todo: Why does this have to be exposed?) ! static size_t commit_alignment() { return commit_alignment_words() * BytesPerWord; } ! static size_t commit_alignment_words(); ! // The largest possible single allocation ! static size_t max_allocation_word_size(); static MetaWord* allocate(ClassLoaderData* loader_data, size_t word_size, MetaspaceObj::Type type, TRAPS); static bool contains(const void* ptr); static bool contains_non_shared(const void* ptr); // Free empty virtualspaces static void purge(); static void report_metadata_oome(ClassLoaderData* loader_data, size_t word_size, ! MetaspaceObj::Type type, Metaspace::MetadataType mdtype, TRAPS); static void print_compressed_class_space(outputStream* st) NOT_LP64({}); // Return TRUE only if UseCompressedClassPointers is True. static bool using_class_space() { return NOT_LP64(false) LP64_ONLY(UseCompressedClassPointers); } ! static bool initialized(); }; ! // ClassLoaderMetaspace is an inbetween-object between a CLD and its MetaspaceArena(s). ! // ! // A CLD owns one MetaspaceArena if compressed class space is off, two if its one ! // (one for allocations of Klass* structures from class space, one for the rest from ! // non-class space). ! // ! // ClassLoaderMetaspace only exists to hide this logic from upper layers: ! // ! // +------+ +----------------------+ +-------------------+ ! // | CLD | ---> | ClassLoaderMetaspace | ----> | (non class) Arena | ! // +------+ +----------------------+ | +-------------------+ allocation top ! // | | v ! // | + chunk -- chunk ... -- chunk ! // | ! // | +-------------------+ ! // +--> | (class) Arena | ! // +-------------------+ ! // | ! // + chunk ... chunk ! // ^ ! // alloc top ! // class ClassLoaderMetaspace : public CHeapObj<mtClass> { ! // A reference to an outside lock, held by the CLD. ! Mutex* const _lock; const Metaspace::MetaspaceType _space_type; ! // Arena for allocations from non-class metaspace ! // (resp. for all allocations if -XX:-UseCompressedClassPointers). ! metaspace::MetaspaceArena* _non_class_space_arena; ! ! // Arena for allocations from class space ! // (NULL if -XX:-UseCompressedClassPointers). ! metaspace::MetaspaceArena* _class_space_arena; Mutex* lock() const { return _lock; } + metaspace::MetaspaceArena* non_class_space_arena() const { return _non_class_space_arena; } + metaspace::MetaspaceArena* class_space_arena() const { return _class_space_arena; } ! metaspace::MetaspaceArena* get_arena(bool is_class) { ! return is_class ? class_space_arena() : non_class_space_arena(); ! } ! public: ! ClassLoaderMetaspace(Mutex* lock, Metaspace::MetaspaceType space_type); ~ClassLoaderMetaspace(); ! Metaspace::MetaspaceType space_type() const { return _space_type; } ! // Allocate word_size words from Metaspace. ! MetaWord* allocate(size_t word_size, Metaspace::MetadataType mdType); ! // Attempt to expand the GC threshold to be good for at least another word_size words ! // and allocate. Returns NULL if failure. Used during Metaspace GC. ! MetaWord* expand_and_allocate(size_t word_size, Metaspace::MetadataType mdType); ! // Prematurely returns a metaspace allocation to the _block_freelists ! // because it is not needed anymore. ! void deallocate(MetaWord* ptr, size_t word_size, bool is_class); ! // Update statistics. This walks all in-use chunks. ! void add_to_statistics(metaspace::clms_stats_t* out) const; ! DEBUG_ONLY(void verify() const;) ! // This only exists for JFR and jcmd VM.classloader_stats. We may want to ! // change this. Capacity as a stat is of questionable use since it may ! // contain committed and uncommitted areas. For now we do this to maintain ! // backward compatibility with JFR. ! void calculate_jfr_stats(size_t* p_used_bytes, size_t* p_capacity_bytes) const; ! }; // end: ClassLoaderMetaspace ! ////////////////// MetaspaceGC /////////////////////// ! // Metaspace are deallocated when their class loader are GC'ed. ! // This class implements a policy for inducing GC's to recover ! // Metaspaces. ! class MetaspaceGCThresholdUpdater : public AllStatic { ! public: ! enum Type { ! ComputeNewSize, ! ExpandAndAllocate, ! Last }; ! static const char* to_string(MetaspaceGCThresholdUpdater::Type updater) { ! switch (updater) { ! case ComputeNewSize: ! return "compute_new_size"; ! case ExpandAndAllocate: ! return "expand_and_allocate"; ! default: ! assert(false, "Got bad updater: %d", (int) updater); ! return NULL; ! }; ! } }; ! class MetaspaceGC : public AllStatic { // The current high-water-mark for inducing a GC. // When committed memory of all metaspaces reaches this value, // a GC is induced and the value is increased. Size is in bytes. static volatile size_t _capacity_until_GC;
*** 475,480 **** --- 289,343 ---- // Calculate the new high-water mark at which to induce // a GC. static void compute_new_size(); }; + + + + class MetaspaceUtils : AllStatic { + public: + + // Committed space actually in use by Metadata + static size_t used_words(); + static size_t used_words(Metaspace::MetadataType mdtype); + + // Space committed for Metaspace + static size_t committed_words(); + static size_t committed_words(Metaspace::MetadataType mdtype); + + // Space reserved for Metaspace + static size_t reserved_words(); + static size_t reserved_words(Metaspace::MetadataType mdtype); + + // _bytes() variants for convenience... + static size_t used_bytes() { return used_words() * BytesPerWord; } + static size_t used_bytes(Metaspace::MetadataType mdtype) { return used_words(mdtype) * BytesPerWord; } + static size_t committed_bytes() { return committed_words() * BytesPerWord; } + static size_t committed_bytes(Metaspace::MetadataType mdtype) { return committed_words(mdtype) * BytesPerWord; } + static size_t reserved_bytes() { return reserved_words() * BytesPerWord; } + static size_t reserved_bytes(Metaspace::MetadataType mdtype) { return reserved_words(mdtype) * BytesPerWord; } + + // (See JDK-8251342). Implement or Consolidate. + static MetaspaceChunkFreeListSummary chunk_free_list_summary(Metaspace::MetadataType mdtype) { + return MetaspaceChunkFreeListSummary(0,0,0,0,0,0,0,0); + } + + // Log change in used metadata. + static void print_metaspace_change(const metaspace::MetaspaceSizesSnapshot& pre_meta_values); + + // This will print out a basic metaspace usage report but + // unlike print_report() is guaranteed not to lock or to walk the CLDG. + static void print_basic_report(outputStream* st, size_t scale = 0); + + // Prints a report about the current metaspace state. + // Function will walk the CLDG and will lock the expand lock; if that is not + // convenient, use print_basic_report() instead. + static void print_report(outputStream* out, size_t scale = 0); + + static void print_on(outputStream * out); + + DEBUG_ONLY(static void verify(bool slow);) + + }; + #endif // SHARE_MEMORY_METASPACE_HPP
< prev index next >