Java在创建对象时,如果恰巧碰到GC导致的STW时,会出现什么情况,对象能正确分配成功吗?

参考代码: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()-…
关注者
40
被浏览
3605
针对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的关系,请跳下面俩传送门: