coleenp@4037: /* coleenp@6678: * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. coleenp@4037: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. coleenp@4037: * coleenp@4037: * This code is free software; you can redistribute it and/or modify it coleenp@4037: * under the terms of the GNU General Public License version 2 only, as coleenp@4037: * published by the Free Software Foundation. coleenp@4037: * coleenp@4037: * This code is distributed in the hope that it will be useful, but WITHOUT coleenp@4037: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or coleenp@4037: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License coleenp@4037: * version 2 for more details (a copy is included in the LICENSE file that coleenp@4037: * accompanied this code). coleenp@4037: * coleenp@4037: * You should have received a copy of the GNU General Public License version coleenp@4037: * 2 along with this work; if not, write to the Free Software Foundation, coleenp@4037: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. coleenp@4037: * coleenp@4037: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA coleenp@4037: * or visit www.oracle.com if you need additional information or have any coleenp@4037: * questions. coleenp@4037: * coleenp@4037: */ coleenp@4037: #ifndef SHARE_VM_MEMORY_METASPACE_HPP coleenp@4037: #define SHARE_VM_MEMORY_METASPACE_HPP coleenp@4037: coleenp@4037: #include "memory/allocation.hpp" coleenp@4037: #include "memory/memRegion.hpp" ehelin@6420: #include "memory/metaspaceChunkFreeListSummary.hpp" coleenp@4037: #include "runtime/virtualspace.hpp" coleenp@4037: #include "utilities/exceptions.hpp" coleenp@4037: coleenp@4037: // Metaspace coleenp@4037: // coleenp@4037: // Metaspaces are Arenas for the VM's metadata. coleenp@4037: // They are allocated one per class loader object, and one for the null coleenp@4037: // bootstrap class loader coleenp@4037: // Eventually for bootstrap loader we'll have a read-only section and read-write coleenp@4037: // to write for DumpSharedSpaces and read for UseSharedSpaces coleenp@4037: // coleenp@4037: // block X ---+ +-------------------+ coleenp@4037: // | | Virtualspace | coleenp@4037: // | | | coleenp@4037: // | | | coleenp@4037: // | |-------------------| coleenp@4037: // | || Chunk | coleenp@4037: // | || | coleenp@4037: // | ||---------- | coleenp@4037: // +------>||| block 0 | | coleenp@4037: // ||---------- | coleenp@4037: // ||| block 1 | | coleenp@4037: // ||---------- | coleenp@4037: // || | coleenp@4037: // |-------------------| coleenp@4037: // | | coleenp@4037: // | | coleenp@4037: // +-------------------+ coleenp@4037: // coleenp@4037: stefank@5771: class ChunkManager; coleenp@4037: class ClassLoaderData; jmasa@4196: class Metablock; stefank@5771: class Metachunk; ehelin@6417: class MetaspaceTracer; coleenp@4037: class MetaWord; coleenp@4037: class Mutex; coleenp@4037: class outputStream; coleenp@4037: class SpaceManager; stefank@5771: class VirtualSpaceList; coleenp@4037: coleenp@4037: // Metaspaces each have a SpaceManager and allocations coleenp@4037: // are done by the SpaceManager. Allocations are done coleenp@4037: // out of the current Metachunk. When the current Metachunk coleenp@4037: // is exhausted, the SpaceManager gets a new one from coleenp@4037: // the current VirtualSpace. When the VirtualSpace is exhausted coleenp@4037: // the SpaceManager gets a new one. The SpaceManager coleenp@4037: // also manages freelists of available Chunks. coleenp@4037: // coleenp@4037: // Currently the space manager maintains the list of coleenp@4037: // virtual spaces and the list of chunks in use. Its coleenp@4037: // allocate() method returns a block for use as a coleenp@4037: // quantum of metadata. coleenp@4037: coleenp@4037: class Metaspace : public CHeapObj { coleenp@4037: friend class VMStructs; coleenp@4037: friend class SpaceManager; coleenp@4037: friend class VM_CollectForMetadataAllocation; coleenp@4037: friend class MetaspaceGC; coleenp@4037: friend class MetaspaceAux; coleenp@4037: coleenp@4037: public: stefank@5863: enum MetadataType { stefank@5863: ClassType, stefank@5863: NonClassType, stefank@5863: MetadataTypeCount jmasa@5162: }; jmasa@4382: enum MetaspaceType { jmasa@4382: StandardMetaspaceType, jmasa@4382: BootMetaspaceType, jmasa@4382: ROMetaspaceType, jmasa@4382: ReadWriteMetaspaceType, jmasa@4382: AnonymousMetaspaceType, jmasa@4382: ReflectionMetaspaceType jmasa@4382: }; coleenp@4037: coleenp@4037: private: jmasa@4382: void initialize(Mutex* lock, MetaspaceType type); jmasa@4382: stefank@5863: // Get the first chunk for a Metaspace. Used for stefank@5863: // special cases such as the boot class loader, reflection stefank@5863: // class loader and anonymous class loader. stefank@5771: Metachunk* get_initialization_chunk(MetadataType mdtype, stefank@5771: size_t chunk_word_size, stefank@5771: size_t chunk_bunch); stefank@5771: jmasa@4382: // Align up the word size to the allocation word size jmasa@4382: static size_t align_word_size_up(size_t); coleenp@4037: hseigel@5528: // Aligned size of the metaspace. coleenp@6029: static size_t _compressed_class_space_size; hseigel@5528: coleenp@6029: static size_t compressed_class_space_size() { coleenp@6029: return _compressed_class_space_size; hseigel@5528: } goetz@6487: coleenp@6029: static void set_compressed_class_space_size(size_t size) { coleenp@6029: _compressed_class_space_size = size; hseigel@5528: } hseigel@5528: coleenp@4037: static size_t _first_chunk_word_size; jmasa@4382: static size_t _first_class_chunk_word_size; coleenp@4037: stefank@5863: static size_t _commit_alignment; stefank@5863: static size_t _reserve_alignment; stefank@5863: coleenp@4037: SpaceManager* _vsm; coleenp@4037: SpaceManager* vsm() const { return _vsm; } coleenp@4037: coleenp@4037: SpaceManager* _class_vsm; coleenp@4037: SpaceManager* class_vsm() const { return _class_vsm; } coleenp@4037: jmasa@5015: // Allocate space for metadata of type mdtype. This is space jmasa@5015: // within a Metachunk and is used by jmasa@5015: // allocate(ClassLoaderData*, size_t, bool, MetadataType, TRAPS) coleenp@4037: MetaWord* allocate(size_t word_size, MetadataType mdtype); coleenp@4037: coleenp@4037: // Virtual Space lists for both classes and other metadata coleenp@4037: static VirtualSpaceList* _space_list; coleenp@4037: static VirtualSpaceList* _class_space_list; coleenp@4037: stefank@5771: static ChunkManager* _chunk_manager_metadata; stefank@5771: static ChunkManager* _chunk_manager_class; stefank@5771: ehelin@6417: static const MetaspaceTracer* _tracer; ehelin@6417: stefank@5771: public: coleenp@4037: static VirtualSpaceList* space_list() { return _space_list; } coleenp@4037: static VirtualSpaceList* class_space_list() { return _class_space_list; } ehelin@5531: static VirtualSpaceList* get_space_list(MetadataType mdtype) { ehelin@5531: assert(mdtype != MetadataTypeCount, "MetadaTypeCount can't be used as mdtype"); ehelin@5531: return mdtype == ClassType ? class_space_list() : space_list(); ehelin@5531: } coleenp@4037: stefank@5771: static ChunkManager* chunk_manager_metadata() { return _chunk_manager_metadata; } stefank@5771: static ChunkManager* chunk_manager_class() { return _chunk_manager_class; } stefank@5771: static ChunkManager* get_chunk_manager(MetadataType mdtype) { stefank@5771: assert(mdtype != MetadataTypeCount, "MetadaTypeCount can't be used as mdtype"); stefank@5771: return mdtype == ClassType ? chunk_manager_class() : chunk_manager_metadata(); stefank@5771: } stefank@5771: ehelin@6417: static const MetaspaceTracer* tracer() { return _tracer; } ehelin@6417: stefank@5771: private: iklam@7089: // These 2 methods are used by DumpSharedSpaces only, where only _vsm is used. So we will iklam@5208: // maintain a single list for now. iklam@5208: void record_allocation(void* ptr, MetaspaceObj::Type type, size_t word_size); iklam@7089: void record_deallocation(void* ptr, size_t word_size); iklam@5208: hseigel@5528: #ifdef _LP64 hseigel@5528: static void set_narrow_klass_base_and_shift(address metaspace_base, address cds_base); hseigel@5528: hseigel@5528: // Returns true if can use CDS with metaspace allocated as specified address. hseigel@5528: static bool can_use_cds_with_metaspace_addr(char* metaspace_base, address cds_base); hseigel@5528: hseigel@5528: static void allocate_metaspace_compressed_klass_ptrs(char* requested_addr, address cds_base); hseigel@5528: hseigel@5528: static void initialize_class_space(ReservedSpace rs); hseigel@5528: #endif hseigel@5528: iklam@5208: class AllocRecord : public CHeapObj { iklam@5208: public: iklam@5208: AllocRecord(address ptr, MetaspaceObj::Type type, int byte_size) iklam@5208: : _next(NULL), _ptr(ptr), _type(type), _byte_size(byte_size) {} iklam@5208: AllocRecord *_next; iklam@5208: address _ptr; iklam@5208: MetaspaceObj::Type _type; iklam@5208: int _byte_size; iklam@5208: }; iklam@5208: iklam@5208: AllocRecord * _alloc_record_head; iklam@5208: AllocRecord * _alloc_record_tail; iklam@5208: hseigel@6027: size_t class_chunk_size(size_t word_size); hseigel@6027: coleenp@4037: public: coleenp@4037: jmasa@4382: Metaspace(Mutex* lock, MetaspaceType type); coleenp@4037: ~Metaspace(); coleenp@4037: stefank@5863: static void ergo_initialize(); coleenp@4037: static void global_initialize(); ehelin@6722: static void post_initialize(); coleenp@4037: coleenp@4037: static size_t first_chunk_word_size() { return _first_chunk_word_size; } jmasa@4382: static size_t first_class_chunk_word_size() { return _first_class_chunk_word_size; } coleenp@4037: stefank@5863: static size_t reserve_alignment() { return _reserve_alignment; } stefank@5863: static size_t reserve_alignment_words() { return _reserve_alignment / BytesPerWord; } stefank@5863: static size_t commit_alignment() { return _commit_alignment; } stefank@5863: static size_t commit_alignment_words() { return _commit_alignment / BytesPerWord; } stefank@5863: coleenp@4037: char* bottom() const; jmasa@5015: size_t used_words_slow(MetadataType mdtype) const; ehelin@5703: size_t free_words_slow(MetadataType mdtype) const; jmasa@5015: size_t capacity_words_slow(MetadataType mdtype) const; coleenp@4037: jmasa@5015: size_t used_bytes_slow(MetadataType mdtype) const; jmasa@5015: size_t capacity_bytes_slow(MetadataType mdtype) const; jmasa@5015: stefank@5941: static MetaWord* allocate(ClassLoaderData* loader_data, size_t word_size, stefank@5941: bool read_only, MetaspaceObj::Type type, TRAPS); jmasa@4064: void deallocate(MetaWord* ptr, size_t byte_size, bool is_class); coleenp@4037: jmasa@4064: MetaWord* expand_and_allocate(size_t size, jmasa@4064: MetadataType mdtype); coleenp@4037: coleenp@6678: static bool contains(const void* ptr); coleenp@6678: coleenp@4037: void dump(outputStream* const out) const; coleenp@4037: jmasa@5007: // Free empty virtualspaces stefank@5771: static void purge(MetadataType mdtype); jmasa@5007: static void purge(); jmasa@5007: stefank@5863: static void report_metadata_oome(ClassLoaderData* loader_data, size_t word_size, ehelin@6419: MetaspaceObj::Type type, MetadataType mdtype, TRAPS); stefank@5863: ehelin@6418: static const char* metadata_type_name(Metaspace::MetadataType mdtype); ehelin@6418: coleenp@4037: void print_on(outputStream* st) const; coleenp@4037: // Debugging support coleenp@4037: void verify(); iklam@5208: iklam@5208: class AllocRecordClosure : public StackObj { iklam@5208: public: iklam@5208: virtual void doit(address ptr, MetaspaceObj::Type type, int byte_size) = 0; iklam@5208: }; iklam@5208: iklam@5208: void iterate(AllocRecordClosure *closure); hseigel@5528: ehelin@5694: // Return TRUE only if UseCompressedClassPointers is True and DumpSharedSpaces is False. hseigel@5528: static bool using_class_space() { ehelin@5694: return NOT_LP64(false) LP64_ONLY(UseCompressedClassPointers && !DumpSharedSpaces); hseigel@5528: } hseigel@5528: mgerdin@5808: static bool is_class_space_allocation(MetadataType mdType) { mgerdin@5808: return mdType == ClassType && using_class_space(); mgerdin@5808: } hseigel@6027: coleenp@4037: }; coleenp@4037: coleenp@4037: class MetaspaceAux : AllStatic { ehelin@5703: static size_t free_chunks_total_words(Metaspace::MetadataType mdtype); jmasa@5015: jmasa@5015: // These methods iterate over the classloader data graph jmasa@5015: // for the given Metaspace type. These are slow. jmasa@5015: static size_t used_bytes_slow(Metaspace::MetadataType mdtype); ehelin@5703: static size_t free_bytes_slow(Metaspace::MetadataType mdtype); jmasa@5015: static size_t capacity_bytes_slow(Metaspace::MetadataType mdtype); ehelin@5703: static size_t capacity_bytes_slow(); coleenp@4037: jmasa@5015: // Running sum of space in all Metachunks that has been jmasa@5015: // allocated to a Metaspace. This is used instead of jmasa@5162: // iterating over all the classloaders. One for each jmasa@5162: // type of Metadata ehelin@6609: static size_t _capacity_words[Metaspace:: MetadataTypeCount]; ehelin@6609: // Running sum of space in all Metachunks that jmasa@5162: // are being used for metadata. One for each jmasa@5162: // type of Metadata. ehelin@6609: static size_t _used_words[Metaspace:: MetadataTypeCount]; jmasa@5015: jmasa@5015: public: jmasa@5015: // Decrement and increment _allocated_capacity_words jmasa@5162: static void dec_capacity(Metaspace::MetadataType type, size_t words); jmasa@5162: static void inc_capacity(Metaspace::MetadataType type, size_t words); jmasa@5015: jmasa@5015: // Decrement and increment _allocated_used_words jmasa@5162: static void dec_used(Metaspace::MetadataType type, size_t words); jmasa@5162: static void inc_used(Metaspace::MetadataType type, size_t words); jmasa@5015: jmasa@5015: // Total of space allocated to metadata in all Metaspaces. jmasa@5015: // This sums the space used in each Metachunk by jmasa@5015: // iterating over the classloader data graph jmasa@5015: static size_t used_bytes_slow() { jmasa@5015: return used_bytes_slow(Metaspace::ClassType) + jmasa@5015: used_bytes_slow(Metaspace::NonClassType); stefank@4371: } coleenp@4037: jmasa@5015: // Used by MetaspaceCounters ehelin@5703: static size_t free_chunks_total_words(); ehelin@5703: static size_t free_chunks_total_bytes(); ehelin@5703: static size_t free_chunks_total_bytes(Metaspace::MetadataType mdtype); jmasa@5015: ehelin@6609: static size_t capacity_words(Metaspace::MetadataType mdtype) { ehelin@6609: return _capacity_words[mdtype]; jmasa@5162: } ehelin@6609: static size_t capacity_words() { ehelin@6609: return capacity_words(Metaspace::NonClassType) + ehelin@6609: capacity_words(Metaspace::ClassType); jmasa@5162: } ehelin@6609: static size_t capacity_bytes(Metaspace::MetadataType mdtype) { ehelin@6609: return capacity_words(mdtype) * BytesPerWord; jmasa@5015: } ehelin@6609: static size_t capacity_bytes() { ehelin@6609: return capacity_words() * BytesPerWord; jmasa@5015: } jmasa@5015: ehelin@6609: static size_t used_words(Metaspace::MetadataType mdtype) { ehelin@6609: return _used_words[mdtype]; jmasa@5162: } ehelin@6609: static size_t used_words() { ehelin@6609: return used_words(Metaspace::NonClassType) + ehelin@6609: used_words(Metaspace::ClassType); jmasa@5162: } ehelin@6609: static size_t used_bytes(Metaspace::MetadataType mdtype) { ehelin@6609: return used_words(mdtype) * BytesPerWord; jmasa@5015: } ehelin@6609: static size_t used_bytes() { ehelin@6609: return used_words() * BytesPerWord; jmasa@5015: } jmasa@5015: jmasa@5015: static size_t free_bytes(); ehelin@5531: static size_t free_bytes(Metaspace::MetadataType mdtype); jmasa@5015: ehelin@5703: static size_t reserved_bytes(Metaspace::MetadataType mdtype); ehelin@5703: static size_t reserved_bytes() { ehelin@5703: return reserved_bytes(Metaspace::ClassType) + ehelin@5703: reserved_bytes(Metaspace::NonClassType); stefank@4371: } coleenp@4037: stefank@5704: static size_t committed_bytes(Metaspace::MetadataType mdtype); stefank@5704: static size_t committed_bytes() { stefank@5704: return committed_bytes(Metaspace::ClassType) + stefank@5704: committed_bytes(Metaspace::NonClassType); stefank@5704: } stefank@5704: ehelin@5703: static size_t min_chunk_size_words(); ehelin@5703: static size_t min_chunk_size_bytes() { ehelin@5703: return min_chunk_size_words() * BytesPerWord; stefank@4371: } coleenp@4037: ehelin@6420: static bool has_chunk_free_list(Metaspace::MetadataType mdtype); ehelin@6420: static MetaspaceChunkFreeListSummary chunk_free_list_summary(Metaspace::MetadataType mdtype); ehelin@6420: coleenp@4037: // Print change in used metadata. coleenp@4037: static void print_metaspace_change(size_t prev_metadata_used); coleenp@4037: static void print_on(outputStream * out); coleenp@4037: static void print_on(outputStream * out, Metaspace::MetadataType mdtype); coleenp@4037: hseigel@5528: static void print_class_waste(outputStream* out); coleenp@4037: static void print_waste(outputStream* out); coleenp@4037: static void dump(outputStream* out); mgerdin@4264: static void verify_free_chunks(); jmasa@5015: // Checks that the values returned by allocated_capacity_bytes() and jmasa@5015: // capacity_bytes_slow() are the same. jmasa@5015: static void verify_capacity(); jmasa@5015: static void verify_used(); jmasa@5015: static void verify_metrics(); coleenp@4037: }; coleenp@4037: coleenp@4037: // Metaspace are deallocated when their class loader are GC'ed. coleenp@4037: // This class implements a policy for inducing GC's to recover coleenp@4037: // Metaspaces. coleenp@4037: coleenp@4037: class MetaspaceGC : AllStatic { coleenp@4037: stefank@5863: // The current high-water-mark for inducing a GC. stefank@5863: // When committed memory of all metaspaces reaches this value, stefank@5863: // a GC is induced and the value is increased. Size is in bytes. stefank@5863: static volatile intptr_t _capacity_until_GC; coleenp@4037: coleenp@4037: // For a CMS collection, signal that a concurrent collection should coleenp@4037: // be started. coleenp@4037: static bool _should_concurrent_collect; coleenp@4037: coleenp@4037: static uint _shrink_factor; coleenp@4037: coleenp@4037: static size_t shrink_factor() { return _shrink_factor; } coleenp@4037: void set_shrink_factor(uint v) { _shrink_factor = v; } coleenp@4037: coleenp@4037: public: coleenp@4037: ehelin@6722: static void initialize(); ehelin@6722: static void post_initialize(); stefank@5863: stefank@5863: static size_t capacity_until_GC(); ehelin@7254: static bool inc_capacity_until_GC(size_t v, ehelin@7254: size_t* new_cap_until_GC = NULL, ehelin@7254: size_t* old_cap_until_GC = NULL); stefank@5863: static size_t dec_capacity_until_GC(size_t v); coleenp@4037: coleenp@4037: static bool should_concurrent_collect() { return _should_concurrent_collect; } coleenp@4037: static void set_should_concurrent_collect(bool v) { coleenp@4037: _should_concurrent_collect = v; coleenp@4037: } coleenp@4037: coleenp@4037: // The amount to increase the high-water-mark (_capacity_until_GC) stefank@5863: static size_t delta_capacity_until_GC(size_t bytes); coleenp@4037: stefank@5863: // Tells if we have can expand metaspace without hitting set limits. stefank@5863: static bool can_expand(size_t words, bool is_class); stefank@5863: stefank@5863: // Returns amount that we can expand without hitting a GC, stefank@5863: // measured in words. stefank@5863: static size_t allowed_expansion(); coleenp@4037: coleenp@4037: // Calculate the new high-water mark at which to induce coleenp@4037: // a GC. coleenp@4037: static void compute_new_size(); coleenp@4037: }; coleenp@4037: coleenp@4037: #endif // SHARE_VM_MEMORY_METASPACE_HPP