hotspot/src/share/vm/runtime/jniHandles.cpp
void JNIHandleBlock::rebuild_free_list() {
{- -------------------------------------------
(1) (assert)
---------------------------------------- -}
assert(_allocate_before_rebuild == 0 && _free_list == NULL, "just checking");
{- -------------------------------------------
(1) (変数宣言など)
---------------------------------------- -}
int free = 0;
int blocks = 0;
{- -------------------------------------------
(1) この JNIHandleBlock オブジェクトから _next フィールドでつながっている全ての JNIHandleBlock オブジェクトを辿り,
_handle 配列中で delete されている箇所 (= JNIHandles::deleted_handle() になっている箇所) を見つけて
free list としてつないでいく
(処理としては単に free list の次の要素へのポインタを埋めていくだけ).
---------------------------------------- -}
for (JNIHandleBlock* current = this; current != NULL; current = current->_next) {
for (int index = 0; index < current->_top; index++) {
oop* handle = &(current->_handles)[index];
if (*handle == JNIHandles::deleted_handle()) {
// this handle was cleared out by a delete call, reuse it
*handle = (oop) _free_list;
_free_list = handle;
free++;
}
}
// we should not rebuild free list if there are unused handles at the end
assert(current->_top == block_size_in_oops, "just checking");
blocks++;
}
{- -------------------------------------------
(1) 次の _allocate_before_rebuild の値を以下のヒューリスティックで計算する.
* _handle 配列中の半分以上が deleted だった場合:
_allocate_before_rebuild は 0 のままとして, 次にブロックが無くなった際には新しい確保は行わないことにする.
(確保せず, すぐさま JNIHandleBlock::rebuild_free_list() を呼ぶ)
* _handle 配列中で deleted の箇所が半分未満だった場合:
_handle 配列中の半分が deleted になる分まで, 新たにブロックの追加を行うこととする.
(次にブロックが無くなった際には, すぐには JNIHandleBlock::rebuild_free_list() は呼ばず,
いくつか新しい JNIHandleBlock を確保してから JNIHandleBlock::rebuild_free_list() を呼ぶこととする.)
---------------------------------------- -}
// Heuristic: if more than half of the handles are free we rebuild next time
// as well, otherwise we append a corresponding number of new blocks before
// attempting a free list rebuild again.
int total = blocks * block_size_in_oops;
int extra = total - 2*free;
if (extra > 0) {
// Not as many free handles as we would like - compute number of new blocks to append
_allocate_before_rebuild = (extra + block_size_in_oops - 1) / block_size_in_oops;
}
{- -------------------------------------------
(1) (トレース出力)
---------------------------------------- -}
if (TraceJNIHandleAllocation) {
tty->print_cr("Rebuild free list JNIHandleBlock " INTPTR_FORMAT " blocks=%d used=%d free=%d add=%d",
this, blocks, total-free, free, _allocate_before_rebuild);
}
}
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.