src/hotspot/share/gc/shared/threadLocalAllocBuffer.inline.hpp
inline HeapWord* ThreadLocalAllocBuffer::allocate(size_t size) { //验证各个内存指针有效,也就是 _top 在 _start 和 _end 范围内 invariants(); HeapWord* obj = top(); //如果空间足够,则分配内存 if (pointer_delta(end(), obj) >= size) { set_top(obj + size); invariants(); return obj; } return NULL; } 9.3.2. TLAB 慢分配src/hotspot/share/gc/shared/memAllocator.cpp
HeapWord* MemAllocator::allocate_inside_tlab_slow(Allocation& allocation) const { HeapWord* mem = NULL; ThreadLocalAllocBuffer& tlab = _thread->tlab(); // 如果 TLAB 剩余空间大于 最大浪费空间,则记录并让最大浪费空间递增 if (tlab.free() > tlab.refill_waste_limit()) { tlab.record_slow_allocation(_word_size); return NULL; } //重新计算 TLAB 大小 size_t new_tlab_size = tlab.compute_size(_word_size); //TLAB 放回 Eden 区 tlab.retire_before_allocation(); if (new_tlab_size == 0) { return NULL; } // 计算最小大小 size_t min_tlab_size = ThreadLocalAllocBuffer::compute_min_size(_word_size); //分配新的 TLAB 空间,并在里面分配对象 mem = Universe::heap()->allocate_new_tlab(min_tlab_size, new_tlab_size, &allocation._allocated_tlab_size); if (mem == NULL) { assert(allocation._allocated_tlab_size == 0, "Allocation failed, but actual size was updated. min: " SIZE_FORMAT ", desired: " SIZE_FORMAT ", actual: " SIZE_FORMAT, min_tlab_size, new_tlab_size, allocation._allocated_tlab_size); return NULL; } assert(allocation._allocated_tlab_size != 0, "Allocation succeeded but actual size not updated. mem at: " PTR_FORMAT " min: " SIZE_FORMAT ", desired: " SIZE_FORMAT, p2i(mem), min_tlab_size, new_tlab_size); //如果启用了 ZeroTLAB 这个 JVM 参数,则将对象所有字段置零值 if (ZeroTLAB) { // ..and clear it. Copy::zero_to_words(mem, allocation._allocated_tlab_size); } else { // ...and zap just allocated object. } //设置新的 TLAB 空间为当前线程的 TLAB tlab.fill(mem, mem + _word_size, allocation._allocated_tlab_size); //返回分配的对象内存地址 return mem; } 9.3.2.1 TLAB最大浪费空间TLAB最大浪费空间 _refill_waste_limit 初始值为 TLAB 大小除以 TLABRefillWasteFraction:
src/hotspot/share/gc/shared/threadLocalAllocBuffer.hpp
每次慢分配,调用record_slow_allocation(size_t obj_size)记录慢分配的同时,增加 TLAB 最大浪费空间的大小:
src/hotspot/share/gc/shared/threadLocalAllocBuffer.cpp
void ThreadLocalAllocBuffer::record_slow_allocation(size_t obj_size) { //每次慢分配,_refill_waste_limit 增加 refill_waste_limit_increment,也就是 TLABWasteIncrement set_refill_waste_limit(refill_waste_limit() + refill_waste_limit_increment()); _slow_allocations++; log_develop_trace(gc, tlab)("TLAB: %s thread: " INTPTR_FORMAT " [id: %2d]" " obj: " SIZE_FORMAT " free: " SIZE_FORMAT " waste: " SIZE_FORMAT, "slow", p2i(thread()), thread()->osthread()->thread_id(), obj_size, free(), refill_waste_limit()); } //refill_waste_limit_increment 就是 JVM 参数 TLABWasteIncrement static size_t refill_waste_limit_increment() { return TLABWasteIncrement; } 9.3.2.2. 重新计算 TLAB 大小重新计算会取 当前堆剩余给 TLAB 可分配的空间 和 TLAB 期望大小 + 当前需要分配的空间大小 中的小的那个:
src/hotspot/share/gc/shared/threadLocalAllocBuffer.inline.hpp
inline size_t ThreadLocalAllocBuffer::compute_size(size_t obj_size) { //获取当前堆剩余给 TLAB 可分配的空间 const size_t available_size = Universe::heap()->unsafe_max_tlab_alloc(thread()) / HeapWordSize; //取 TLAB 可分配的空间 和 TLAB 期望大小 + 当前需要分配的空间大小 以及 TLAB 最大大小中的小的那个 size_t new_tlab_size = MIN3(available_size, desired_size() + align_object_size(obj_size), max_size()); // 确保大小大于 dummy obj 对象头 if (new_tlab_size < compute_min_size(obj_size)) { log_trace(gc, tlab)("ThreadLocalAllocBuffer::compute_size(" SIZE_FORMAT ") returns failure", obj_size); return 0; } log_trace(gc, tlab)("ThreadLocalAllocBuffer::compute_size(" SIZE_FORMAT ") returns " SIZE_FORMAT, obj_size, new_tlab_size); return new_tlab_size; } 9.3.2.3. 当前 TLAB 放回堆