源码分析:Java对象的内存分配(3)

HeapWord* CollectedHeap::common_mem_allocate_init(size_t size, bool is_noref, TRAPS) {
  HeapWord* obj = common_mem_allocate_noinit(size, is_noref, CHECK_NULL);
  init_obj(obj, size);
  return obj;
}

  6.common_mem_allocate_noinit()如下:
  (1).若使用了本地线程分配缓冲TLAB,则会调用allocate_from_tlab()尝试从TLAB中分配内存

HeapWord* result = NULL;
  if (UseTLAB) {
    result = CollectedHeap::allocate_from_tlab(THREAD, size);
    if (result != NULL) {
      assert(!HAS_PENDING_EXCEPTION,
            "Unexpected exception, will result in uninitialized storage");
      return result;
    }
  }

  (2).否则会调用堆的mem_allocate()尝试分配

 

bool gc_overhead_limit_was_exceeded = false;
  result = Universe::heap()->mem_allocate(size,
                                          is_noref,
                                          false,
                                          &gc_overhead_limit_was_exceeded);

  (3).统计分配的字节数

if (result != NULL) {
  //...
    THREAD->incr_allocated_bytes(size * HeapWordSize);
    return result;
  }

  (4).否则说明申请失败,若在申请过程中gc没有超时,则抛出OOM异常

if (!gc_overhead_limit_was_exceeded) {
    // -XX:+HeapDumpOnOutOfMemoryError and -XX:OnOutOfMemoryError support
    report_java_out_of_memory("Java heap space");

if (JvmtiExport::should_post_resource_exhausted()) {
      JvmtiExport::post_resource_exhausted(
        JVMTI_RESOURCE_EXHAUSTED_OOM_ERROR | JVMTI_RESOURCE_EXHAUSTED_JAVA_HEAP,
        "Java heap space");
    }

THROW_OOP_0(Universe::out_of_memory_error_java_heap());

  7.对象内存分配后的初始化过程包括两部分,一个是init_obj()完成对对象内存空间的对齐和填充,一个是post_allocation_setup_obj()对堆上的oop对象进行初始化。

  (1).init_obj():

void CollectedHeap::init_obj(HeapWord* obj, size_t size) {
  assert(obj != NULL, "cannot initialize NULL object");
  const size_t hs = oopDesc::header_size();
  assert(size >= hs, "unexpected object size");
  ((oop)obj)->set_klass_gap(0);
  Copy::fill_to_aligned_words(obj + hs, size - hs);
}

  hs就是对象头的大小,fill_to_aligned_words将对象空间除去对象头的部分做填0处理,该函数定义在/hotspot/src/share/vm/utilities/copy.h中,并转而调用pd_fill_to_aligned_words()。
  pd_fill_to_aligned_words根据不同平台实现,以x86平台为例,该函数定义在/hotspot/src/cpu/x86/vm/copy_x86.h中:

static void pd_fill_to_words(HeapWord* tohw, size_t count, juint value) {
#ifdef AMD64
  julong* to = (julong*) tohw;
  julong  v  = ((julong) value << 32) | value;
  while (count-- > 0) {
    *to++ = v;
  }
#else
  juint* to = (juint*)tohw;
  count *= HeapWordSize / BytesPerInt;
  while (count-- > 0) {
    *to++ = value;
  }
#endif // AMD64
}

  该函数的作用就是先将地址类型转换,然后把堆的字数转化为字节数,再对该段内存进行填值(value = 0)处理

  (2).post_allocation_setup_obj()调用了post_allocation_setup_common()进行初始化工作,然后调用post_allocation_notify()通知JVMTI和dtrace
  

void CollectedHeap::post_allocation_setup_obj(KlassHandle klass,
                                              HeapWord* obj,
                                              size_t size) {
  post_allocation_setup_common(klass, obj, size);
  assert(Universe::is_bootstrapping() ||
        !((oop)obj)->blueprint()->oop_is_array(), "must not be an array");
  // notify jvmti and dtrace
  post_allocation_notify(klass, (oop)obj);
}

  post_allocation_setup_common()如下:

void CollectedHeap::post_allocation_setup_common(KlassHandle klass,
                                                HeapWord* obj,
                                                size_t size) {
  post_allocation_setup_no_klass_install(klass, obj, size);
  post_allocation_install_obj_klass(klass, oop(obj), (int) size);
}

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/d99615c53ee9166c69daae92f15e67af.html