これらは, HotSpot 内で定義されている (ほとんど) 全てのクラスの基底クラス群 (See: here and here for details).
C ヒープ上に確保されるオブジェクト用の基底クラス (See: here for details).
((cite: hotspot/src/share/vm/memory/allocation.hpp))
class CHeapObj ALLOCATION_SUPER_CLASS_SPEC {
See: here for details
スタック上に確保されるオブジェクト用の基底クラス (See: here for details).
((cite: hotspot/src/share/vm/memory/allocation.hpp))
// Base class for objects allocated on the stack only.
// Calling new or delete will result in fatal error.
class StackObj ALLOCATION_SUPER_CLASS_SPEC {
See: here for details
常に値渡しで使われるオブジェクト用の基底クラス (See: here for details).
((cite: hotspot/src/share/vm/memory/allocation.hpp))
// Base class for objects used as value objects.
// Calling new or delete will result in fatal error.
...
//
class _ValueObj {
See: here for details
静的にメモリを確保するオブジェクト用の基底クラス (See: here for details).
((cite: hotspot/src/share/vm/memory/allocation.hpp))
// Base class for classes that constitute name spaces.
class AllStatic {
See: here for details
Arena クラス内で使用される補助クラス (See: here for details).
開放されたメモリ領域を管理し, 次回の確保要求に備える.
((cite: hotspot/src/share/vm/memory/allocation.hpp))
//------------------------------Chunk------------------------------------------
// Linked list of raw memory chunks
class Chunk: public CHeapObj {
See: here for details
C ヒープ内でのメモリ確保を効率的に行うためのクラス (See: here for details).
((cite: hotspot/src/share/vm/memory/allocation.hpp))
//------------------------------Arena------------------------------------------
// Fast allocation of memory
class Arena: public CHeapObj {
See: here for details
ResourceArea に確保されるオブジェクト(= スレッドローカルで一時的なオブジェクト)用の基底クラス (See: here for details).
((cite: hotspot/src/share/vm/memory/allocation.hpp))
//----------------------------------------------------------------------
// Base class for objects allocated in the resource area per default.
// Optionally, objects may be allocated on the C heap with
// new(ResourceObj::C_HEAP) Foo(...) or in an Arena with new (&arena)
// ResourceObj's can be allocated within other objects, but don't use
// new or delete (allocation_type is unknown). If new is used to allocate,
// use delete to deallocate.
class ResourceObj ALLOCATION_SUPER_CLASS_SPEC {
See: here for details
デバッグ用(開発時用)のクラス (#ifndef PRODUCT 時にしか定義されない).
デバッグ時における (ほとんど) 全てのクラスの基底クラス.
#ifndef PRODUCT
時には (ほとんど) 全てのクラスがこのクラスのサブクラスになる
(より正確に言うと, #ifndef PRODUCT
時にはこのクラスが CHeapObj, StackObj, ResourceObj のスーパークラスになる) (See: here for details).
内部にそのオブジェクトの情報を出力する print() メソッド及び print_value() メソッドを定義しているため, デバッグ時には (ほとんど) 全てのクラスで情報出力が行えるようになる.
なお, 実際の使用箇所では ALLOCATION_SUPER_CLASS_SPEC という名前で使用される. デバッグ時にはこれが AllocatedObj の別名になる. デバッグ時以外には ALLOCATION_SUPER_CLASS_SPEC は空文字列になるため, CHeapObj, StackObj, ResourceObj はスーパークラスを持たないクラスになる.
((cite: hotspot/src/share/vm/memory/allocation.hpp))
// Base class for objects allocated in the C-heap.
// In non product mode we introduce a super class for all allocation classes
// that supports printing.
// We avoid the superclass in product mode since some C++ compilers add
// a word overhead for empty super classes.
#ifdef PRODUCT
#define ALLOCATION_SUPER_CLASS_SPEC
#else
#define ALLOCATION_SUPER_CLASS_SPEC : public AllocatedObj
class AllocatedObj {
See: here for details
デバッグ用(開発時用)のクラス (#ifndef PRODUCT 時にしか定義されない).
C ヒープ内でのメモリ確保処理に関する統計情報を表示するためのクラス.
(例えば, malloc() や free() の呼び出し回数, 確保した量(バイト数), 開放した量(バイト数), etc)
((cite: hotspot/src/share/vm/memory/allocation.hpp))
// for statistics
#ifndef PRODUCT
class AllocStats : StackObj {
コンストラクタ内で, その時点での各指標の値(os::num_mallocs, os::num_frees, etc)が記録される.
AllocStats::print() が呼ばれると, 記録していた値とその時点での値の差分を表示する.
((cite: hotspot/src/share/vm/memory/allocation.cpp))
AllocStats::AllocStats() {
start_mallocs = os::num_mallocs;
start_frees = os::num_frees;
start_malloc_bytes = os::alloc_bytes;
start_mfree_bytes = os::free_bytes;
start_res_bytes = Arena::_bytes_allocated;
}
julong AllocStats::num_mallocs() { return os::num_mallocs - start_mallocs; }
julong AllocStats::alloc_bytes() { return os::alloc_bytes - start_malloc_bytes; }
julong AllocStats::num_frees() { return os::num_frees - start_frees; }
julong AllocStats::free_bytes() { return os::free_bytes - start_mfree_bytes; }
julong AllocStats::resource_bytes() { return Arena::_bytes_allocated - start_res_bytes; }
void AllocStats::print() {
tty->print_cr(UINT64_FORMAT " mallocs (" UINT64_FORMAT "MB), "
UINT64_FORMAT" frees (" UINT64_FORMAT "MB), " UINT64_FORMAT "MB resrc",
num_mallocs(), alloc_bytes()/M, num_frees(), free_bytes()/M, resource_bytes()/M);
}
インスタンスは alloc_stats という大域変数に格納されている.
((cite: hotspot/src/share/vm/runtime/java.cpp))
AllocStats alloc_stats;
print_statistics() 関数の中で呼び出されている.
(ただし, PrintMallocStatistics オプションが指定されている場合にのみ, 出力が行われる)
((cite: hotspot/src/share/vm/runtime/java.cpp))
void print_statistics() {
...
if (PrintMallocStatistics) {
tty->print("allocation stats: ");
alloc_stats.print();
tty->cr();
}
See: here for details
デバッグ用(開発時用)のクラス.
ResourceArea 内に確保した配列を REALLOC_RESOURCE_ARRAY() で伸ばす際に, その配列が ResourceMark によって既に解放されていないかどうかをチェックする.
((cite: hotspot/src/share/vm/memory/allocation.hpp))
//------------------------------ReallocMark---------------------------------
// Code which uses REALLOC_RESOURCE_ARRAY should check an associated
// ReallocMark, which is declared in the same scope as the reallocated
// pointer. Any operation that could __potentially__ cause a reallocation
// should check the ReallocMark.
class ReallocMark: public StackObj {
コンストラクタが呼び出された時点と ReallocMark::check() が呼び出された時点とで ResourceArea の nest レベル (以下の nesting) をチェックし, もしレベルが異なっていれば fatal() で異常終了させる (なお開発時用の機能であるため, #ifdef ASSERT 時以外はコードは全て空になる).
((cite: hotspot/src/share/vm/memory/allocation.cpp))
ReallocMark::ReallocMark() {
#ifdef ASSERT
Thread *thread = ThreadLocalStorage::get_thread_slow();
_nesting = thread->resource_area()->nesting();
#endif
}
void ReallocMark::check() {
#ifdef ASSERT
if (_nesting != Thread::current()->resource_area()->nesting()) {
fatal("allocation bug: array could grow within nested ResourceMark");
}
#endif
}
なお, ResourceArea::nesting() は ResourceMark によって増減される値 (ResourceMark のコンストラクタが呼ばれるとインクリメントされ, ResourceMark のデストラクタが呼ばれるとデクリメントされる.)
((cite: hotspot/src/share/vm/memory/resourceArea.hpp))
ResourceMark( ResourceArea *r ) :
...
debug_only(_area->_nesting++;)
...
}
...
~ResourceMark() {
...
debug_only(_area->_nesting--;)
...
}
See: here for details
Chunk クラス内で使用される補助クラス (See: here for details).
未使用の Chunk を管理するためのフリーリスト.
(なお, thread の初期化が終わる前から使用されるため, 内部で mutex は使わないように, とのこと.)
((cite: hotspot/src/share/vm/memory/allocation.cpp))
//--------------------------------------------------------------------------------------
// ChunkPool implementation
// MT-safe pool of chunks to reduce malloc/free thrashing
// NB: not using Mutex because pools are used before Threads are initialized
class ChunkPool {
See: here for details
Chunk クラス用の補助クラス (See: here for details).
ChunkPool 内の Chunk 数が多くなりすぎないように, 定期間隔で ChunkPool 内の Chunk を解放するためのクラス(PeriodicTaskクラス).
((cite: hotspot/src/share/vm/memory/allocation.cpp))
//--------------------------------------------------------------------------------------
// ChunkPoolCleaner implementation
//
class ChunkPoolCleaner : public PeriodicTask {
定期間隔で ChunkPool::clean() を呼び出しているだけ.
((cite: hotspot/src/share/vm/memory/allocation.cpp))
void task() {
ChunkPool::clean();
}
なお, 現在の処理間隔は 5 秒.
((cite: hotspot/src/share/vm/memory/allocation.cpp))
enum { CleaningInterval = 5000 }; // cleaning interval in ms
呼び出される ChunkPool::clean() の中では, 各 ChunkPool の要素を最大 5 個を残して解放する.
((cite: hotspot/src/share/vm/memory/allocation.cpp))
static void clean() {
enum { BlocksToKeep = 5 };
_small_pool->free_all_but(BlocksToKeep);
_medium_pool->free_all_but(BlocksToKeep);
_large_pool->free_all_but(BlocksToKeep);
}
ChunkPool::free_all_but() の処理は以下の通り (ChunkPool 内に指定された個数以上に Chunk が入っていれば, 指定個数まで解放する).
((cite: hotspot/src/share/vm/memory/allocation.cpp))
// Prune the pool
void free_all_but(size_t n) {
// if we have more than n chunks, free all of them
ThreadCritical tc;
if (_num_chunks > n) {
// free chunks at end of queue, for better locality
Chunk* cur = _first;
for (size_t i = 0; i < (n - 1) && cur != NULL; i++) cur = cur->next();
if (cur != NULL) {
Chunk* next = cur->next();
cur->set_next(NULL);
cur = next;
// Free all remaining chunks
while(cur != NULL) {
next = cur->next();
os::free(cur);
_num_chunks--;
cur = next;
}
}
}
}
See: here for details
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.