jvm源码阅读笔记[3]:从内存分配到触发GC的细节

    从零开始看源码,旨在从源码验证书上的结论,探索书上未知的细节。有疑问欢迎留言探讨
    个人源码地址:https://github.com/FlashLightNing/openjdk-notes
    还有一个openjdk6,7,8,9的地址:https://github.com/dmlloyd/openjdk
    jvm源码阅读笔记[1]:如何触发一次CMS回收
    jvm源码阅读笔记[2]:你不知道的晋升阈值TenuringThreshold详解
    jvm源码阅读笔记[3]:从内存分配到触发GC的细节
    jvm源码阅读笔记[4]:从GC说到vm operation
    jvm源码阅读笔记[5]:内存分配失败触发的GC究竟对内存做了什么?

    
    除了第一篇说到的,对于使用cms回收的应用,会有线程轮询判断老年代是否满足GC的条件,若满足,则会触发一次cms老年代的回收。
    针对年轻代,更常见的是,线程优先在eden区分配对象的时候,若eden区空间不足,则会触发一次young gc。若不允许担保失败,则还可能转为一次full gc。那么,今天就来看看这种内存分配不足触发GC的过程。
    以下是collectedHeap.inline.hpp中的分配的代码。
    

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");//校验在GC的时候不会进行内存分配
  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, size);
  NOT_PRODUCT(Universe::heap()->check_for_bad_heap_word_value(obj, size));
  return (oop)obj;
}

    
    collectedHeap定义了Java堆的实现,定义了堆必须实现的功能,如创建TLAB,内存分配等基本功能。然后其他类通过继承collectedHeap类,实现了几种具体的堆类型,主要有ParallelScavengeHeap,G1CollectedHeap等。这些细节以后再写。
    从源码中可以看到,首先是一些简单的校验,如当前堆不处于GC状态,分配的大小>0。然后再调用common_mem_allocate_init方法进行内存分配,再是调用post_allocation_setup_obj做一些初始化的工作,如设置对象头信息等。
    来看看common_mem_allocate_init方法:
    

HeapWord* CollectedHeap::common_mem_allocate_init(KlassHandle klass, size_t size, TRAPS) {
  HeapWord* obj = common_mem_allocate_noinit(klass, size, CHECK_NULL);
  init_obj(obj, size);//字节填充和对齐
  return obj;
}

    
    它先是调用common_mem_allocate_noinit方法申请了内存空间,然后调用init_obj方法进行初始化,这里的初始化主要是为申请出来的这块空间填充0字节和字节对齐。
    还是来看看common_mem_allocate_noinit方法吧。
    


HeapWord* CollectedHeap::common_mem_allocate_noinit(KlassHandle klass, size_t size, TRAPS) {

  CHECK_UNHANDLED_OOPS_ONLY(THREAD->clear_unhandled_oops();)

  if (HAS_PENDING_EXCEPTION) {
    NOT_PRODUCT(guarantee(false, "Should not allocate with exception pending"));
    return NULL;  // caller does a CHECK_0 too
  }

  HeapWord* result = NULL;
  if (UseTLAB) {
  //在tlab里分配
    result = allocate_from_tlab(klass, THREAD, size);
    if (result != NULL) {
      assert(!HAS_PENDING_EXCEPTION,
             "Unexpected exception, will result in uninitialized storage");
      return result;
    }
  }
  bool gc_overhead_limit_was_exceeded = false;
   //在堆中分配
  result = Univer
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值