问题描述
参考代码:
oop CollectedHeap::obj_allocate(KlassHandle klass, int size, TRAPS) {
debug_only(check_for_valid_allocation_state());
assert(!Universe::heap()->is_gc_active(), "Allocation during gc not allowed");
assert(size >= 0, "int won't convert to size_t");
HeapWord* obj = common_mem_allocate_init(klass, size, CHECK_NULL);
post_allocation_setup_obj(klass, obj);
NOT_PRODUCT(Universe::heap()->check_for_bad_heap_word_value(obj, size));
return (oop)obj;
}
针对HotSpot VM的情况回答这个问题:new动作不会在STW过程中执行,而是必须等STW结束才可以继续执行。
HotSpot VM的stop-the-world(STW)只有一种模式,那就是把所有Java线程都暂停下来。
一个new动作必须要在一个Java线程能运行的时候才可以执行得了。如果VM当前正在STW,正在或者即将尝试执行new动作的Java线程也必然跟其它Java线程一样被暂停了,要等触发STW的动作(例如GC)结束后才可以继续执行。
在STW结束后,Java线程恢复运行时,就像是做了场梦然后醒过来一样,先前该做啥就继续做啥,并不会感知STW过程中发生了什么事。假如一个Java线程在STW前正在执行new(它很可能就是这次STW的触发者了…),那么GC STW后它继续执行,还是照旧去看看当前GC堆里还有没有足够空间可满足这次分配请求,有的话就分配并返回,没有的话就要么触发GC要么抛OOME,一切照常。
题主的问题描述里引用了CollectedHeap::obj_allocate()的代码:
oop CollectedHeap::obj_allocate(KlassHandle klass, int size, TRAPS) {
debug_only(check_for_valid_allocation_state());
assert(!Universe::heap()->is_gc_active(), "Allocation during gc not allowed");
assert(size >= 0, "int won't convert to size_t");
HeapWord* obj = common_mem_allocate_init(klass, size, CHECK_NULL);
post_allocation_setup_obj(klass, obj);
NOT_PRODUCT(Universe::heap()->check_for_bad_heap_word_value(obj, size));
return (oop)obj;
}
这个函数自身有可能会触发GC(经由它所调用的 common_mem_allocate_init() 一直下去会到可能触发GC的地方),但这个函数被调用的时候,当前不可以正在执行一个STW GC。
关于Java线程在STW时是如何暂停下来的,及其它与safepoint的关系,请跳下面俩传送门: