inline instanceOop InstanceKlass::allocate_instance(oop java_class, TRAPS){ Klass* k = java_lang_Class::as_Klass(java_class); if (k == NULL) { ResourceMark rm(THREAD); THROW_(vmSymbols::java_lang_InstantiationException(), NULL); } InstanceKlass* ik = cast(k); ik->check_valid_for_instantiation(false, CHECK_NULL); ik->initialize(CHECK_NULL); return ik->allocate_instance(THREAD); }
最后一步直接调用InstanceKlass的allocate_instance(THREAD)方法
1 2 3 4 5 6 7 8 9 10 11 12
instanceOop InstanceKlass::allocate_instance(TRAPS){ bool has_finalizer_flag = has_finalizer(); // Query before possible GC int size = size_helper(); // Query before forming handle.
instanceOop i;
i = (instanceOop)Universe::heap()->obj_allocate(this, size, CHECK_NULL); if (has_finalizer_flag && !RegisterFinalizersAtInit) { i = register_finalizer(i, CHECK_NULL); } return i; }
oop MemAllocator::allocate()const{ oop obj = NULL; { Allocation allocation(*this, &obj); HeapWord* mem = mem_allocate(allocation); if (mem != NULL) { obj = initialize(mem); } else { // The unhandled oop detector will poison local variable obj, // so reset it to NULL if mem is NULL. obj = NULL; } } return obj; }
继续看mem_allocate(allocation);
1 2 3 4 5 6 7 8 9 10
HeapWord* MemAllocator::mem_allocate(Allocation& allocation)const{ if (UseTLAB) { HeapWord* result = allocate_inside_tlab(allocation); if (result != NULL) { return result; } }
HeapWord* GenCollectedHeap::mem_allocate_work(size_t size, bool is_tlab, bool* gc_overhead_limit_was_exceeded){ // In general gc_overhead_limit_was_exceeded should be false so // set it so here and reset it to true only if the gc time // limit is being exceeded as checked below. *gc_overhead_limit_was_exceeded = false;
HeapWord* result = NULL;
// Loop until the allocation is satisfied, or unsatisfied after GC. for (uint try_count = 1, gclocker_stalled_count = 0; /* return or throw */; try_count += 1) {
// First allocation attempt is lock-free. Generation *young = _young_gen; assert(young->supports_inline_contig_alloc(), "Otherwise, must do alloc within heap lock"); if (young->should_allocate(size, is_tlab)) { result = young->par_allocate(size, is_tlab); if (result != NULL) { assert(is_in_reserved(result), "result not in heap"); return result; } } uint gc_count_before; // Read inside the Heap_lock locked region. { MutexLocker ml(Heap_lock); log_trace(gc, alloc)("GenCollectedHeap::mem_allocate_work: attempting locked slow path allocation"); // Note that only large objects get a shot at being // allocated in later generations. bool first_only = !should_try_older_generation_allocation(size);
result = attempt_allocation(size, is_tlab, first_only); if (result != NULL) { assert(is_in_reserved(result), "result not in heap"); return result; }
if (GCLocker::is_active_and_needs_gc()) { if (is_tlab) { returnNULL; // Caller will retry allocating individual object. } if (!is_maximal_no_gc()) { // Try and expand heap to satisfy request. result = expand_heap_and_allocate(size, is_tlab); // Result could be null if we are out of space. if (result != NULL) { return result; } }
if (gclocker_stalled_count > GCLockerRetryAllocationCount) { returnNULL; // We didn't get to do a GC and we didn't get any memory. }
// If this thread is not in a jni critical section, we stall // the requestor until the critical section has cleared and // GC allowed. When the critical section clears, a GC is // initiated by the last thread exiting the critical section; so // we retry the allocation sequence from the beginning of the loop, // rather than causing more, now probably unnecessary, GC attempts. JavaThread* jthr = JavaThread::current(); if (!jthr->in_critical()) { MutexUnlocker mul(Heap_lock); // Wait for JNI critical section to be exited GCLocker::stall_until_clear(); gclocker_stalled_count += 1; continue; } else { if (CheckJNICalls) { fatal("Possible deadlock due to allocating while" " in jni critical section"); } returnNULL; } }
// Read the gc count while the heap lock is held. gc_count_before = total_collections(); }
VM_GenCollectForAllocation op(size, is_tlab, gc_count_before); VMThread::execute(&op); if (op.prologue_succeeded()) { result = op.result(); if (op.gc_locked()) { assert(result == NULL, "must be NULL if gc_locked() is true"); continue; // Retry and/or stall as necessary. }
// Allocation has failed and a collection // has been done. If the gc time limit was exceeded the // this time, return NULL so that an out-of-memory // will be thrown. Clear gc_overhead_limit_exceeded // so that the overhead exceeded does not persist.