Hotspot 内存管理之MemoryService 源码解析

    目录

一、MemoryPool

1、定义

2、oops_do

3、get_memory_pool_instance 

4、MemoryUsage / ThresholdSupport /  SensorInfo

二、MemoryManager

1、定义

2、get_memory_manager_instance

三、GCMemoryManager

1、定义

扫描二维码关注公众号,回复: 9043701 查看本文章

2、gc_begin/gc_end

3、GCNotifier pushNotification 和 sendNotificationInternal

四、MemoryService 

 1、set_universe_heap

 2、gc_begin /  gc_end


       上一篇《Hotspot 内存管理之CodeCache 源码解析》讲解了CodeCache::initialize()方法的实现,当CodeCache的_heap属性通过CodeHeap::reserve方法初始化完成后就会调用MemoryService::add_code_heap_memory_pool方法将这个_heap管理起来,如下图:

MemoryService负责缓存JVM中所有的类似CodeCache这样的大块内存的内存使用和GC的数据,主要为java.lang.management API提供内存管理相关接口的底层实现,本篇博客就详细探讨MemoryService相关类的使用与实现。

一、MemoryPool

1、定义

     MemoryPool代表一块由JVM管理的内存区域,可以在运行时由JVM创建或者移除。MemoryPool只有两种类型,Heap或者NonHeap,通过枚举PoolType表示,部分MemoryPool可能同时属于这两种类型。MemoryPool的定义位于hotspot src/shared/vm/service/memoryPool.hpp中,其包含的属性如下:

  • const char*      _name;   //名字
  •   PoolType         _type;   //类型
  •   size_t           _initial_size;  //初始大小
  •   size_t           _max_size;   //最大大小
  •   bool             _available_for_allocation; //能否分配内存,默认为true
  •   MemoryManager*   _managers[max_num_managers];  //该MemoryPool所属的MemoryManager数组,max_num_managers是一个枚举值,为5
  •   int              _num_managers;  //该MemoryPool的MemoryManager的个数
  •   MemoryUsage      _peak_usage;               // 用来记录MemoryUsage各指标的在GC前的历史最高值
  •   MemoryUsage      _after_gc_usage;           // GC结束后的内存占用情况
  •   ThresholdSupport* _usage_threshold;     //
  •   ThresholdSupport* _gc_usage_threshold;  //触发GC的阈值
  •   SensorInfo*      _usage_sensor;  //达到阈值时触发的动作
  •   SensorInfo*      _gc_usage_sensor;
  •   volatile instanceOop _memory_pool_obj;  //该MemoryPool对应的Java对象实例

MemoryPool定义的方法都是操作相关属性的,重点关注oops_do和get_memory_pool_instance的实现即可。

MemoryPool的类继承关系如下:

其中CodeHeapPool对应于CodeCache管理的内存,CollectedMemoryPool及其子类对应分配Java对象的堆内存,CompressedKlassSpacePool对应于保存压缩的Klass信息的内存,MetaspacePool对应保存元数据的内存。

2、oops_do

oops_do方法用于GC时遍历对象引用的,其调用链如下:

该方法的实现如下:

void MemoryPool::oops_do(OopClosure* f) {
  f->do_oop((oop*) &_memory_pool_obj);
  if (_usage_sensor != NULL) {
    _usage_sensor->oops_do(f);
  }
  if (_gc_usage_sensor != NULL) {
    _gc_usage_sensor->oops_do(f);
  }
}

void SensorInfo::oops_do(OopClosure* f) {
  f->do_oop((oop*) &_sensor_obj);
}

即分别以_memory_pool_obj和_usage_sensor/_gc_usage_sensor中的_sensor_obj对象为根对象遍历,找到所有引用了这三个对象的对象。这三个在MemoryPool构造时都是NULL,构造方法实现如下:

 _memory_pool_obj属性的初始化参考下面的get_memory_pool_instance方法的说明,_usage_sensor和_gc_usage_sensor都是通过对应的set方法实现,如下图:

以 set_usage_sensor_obj方法的调用链为例说明,如下图:

jmm_interface就是JVM提供的用于获取内存使用情况,Java线程运行等的接口,是 java.lang.management API在JVM层的具体实现,jmm_interface的定义位于同目录的jmm.h中,搜索其中SetPoolSensor方法的调用链如下:

调用的代码如下:

这就是JNI本地方法的实现,对应的类sun.management.MemoryPoolImpl就是java.lang.management.MemoryPoolMXBean的具体实现类,可通过java.lang.management.ManagementFactory.getMemoryPoolMXBeans方法获取。

 3、get_memory_pool_instance 

    get_memory_pool_instance用于创建一个对应的MemoryPoolImpl类的实例,从而可以通过java.lang.management API获取该MemoryPool的内存使用情况,其源码说明如下:

instanceOop MemoryPool::get_memory_pool_instance(TRAPS) {
  // load_ptr_acquire是将其强转成volatile指针,即获取该值的最新值
  instanceOop pool_obj = (instanceOop)OrderAccess::load_ptr_acquire(&_memory_pool_obj);
  if (pool_obj == NULL) {
    // 获取sun_management_ManagementFactory对应的Klass
    Klass* k = Management::sun_management_ManagementFactory_klass(CHECK_NULL);
    instanceKlassHandle ik(THREAD, k);
    
    //创建一个Java String对象
    Handle pool_name = java_lang_String::create_from_str(_name, CHECK_NULL);
    jlong usage_threshold_value = (_usage_threshold->is_high_threshold_supported() ? 0 : -1L);
    jlong gc_usage_threshold_value = (_gc_usage_threshold->is_high_threshold_supported() ? 0 : -1L);

    JavaValue result(T_OBJECT);
    JavaCallArguments args;
    //方法参数
    args.push_oop(pool_name);           // Argument 1
    args.push_int((int) is_heap());     // Argument 2
    
    //方法名
    Symbol* method_name = vmSymbols::createMemoryPool_name();
    //方法签名
    Symbol* signature = vmSymbols::createMemoryPool_signature();

    args.push_long(usage_threshold_value);    // Argument 3
    args.push_long(gc_usage_threshold_value); // Argument 4

    //调用createMemoryPool(String name, boolean isHeap, long uThreshold, long gcThreshold)方法
    JavaCalls::call_static(&result,
                           ik,
                           method_name,
                           signature,
                           &args,
                           CHECK_NULL);
    //获取createMemoryPool方法的执行结果
    instanceOop p = (instanceOop) result.get_jobject();
    instanceHandle pool(THREAD, p);

    {
      //获取锁,
      MutexLocker ml(Management_lock);
      //如果其他线程已经创建了该实例则返回
      pool_obj = (instanceOop)OrderAccess::load_ptr_acquire(&_memory_pool_obj);
      if (pool_obj != NULL) {
         return pool_obj;
      }
      pool_obj = pool();
      //原子的设置_memory_pool_obj属性
      OrderAccess::release_store_ptr(&_memory_pool_obj, pool_obj);
    }
  }

  return pool_obj;
}

get_memory_pool_instance实际调用的Java方法如下图:

 get_memory_pool_instance的调用链如下:

 jmmInterface_1_的GetMemoryPools方法的调用链如下:

4、MemoryUsage / ThresholdSupport /  SensorInfo

     MemoryUsage的定义在hotspot src/shared/vm/service/memoryUsage.hpp中, 对应Java类是java.lang.management.MemoryUsage,两者的属性是一一对应,如下图:

其中initSize表示初始大小,used表示已经使用的大小,committed表示已经分配内存可以被JVM直接利用的空间大小,committed会随着时间变化而变化,但肯定大于used,maxSize表示能够使用的最大的空间大小。

    SensorInfo的定义位于同目录的lowMemoryDetector.hpp中,对应的Java类是sun.management.Sensor,这是一个抽象类,sun.management.MemoryPoolImpl中定义了两个内部实现类,PoolSensor和CollectionSensor。参考MemoryPoolImpl的初始化,如下图:

PoolSensor和CollectionSensor的核心动作就是发送消息,如下图:

可以通过javax.management.StandardEmitterMBean.addNotificationListener方法增加监听消息。当某个MemoryPool的内存使用率超过设置的阈值时就会通过Sensor发送消息。

 ThresholdSupport的定义在同目录的lowMemoryDetector.hpp中,该类没有对应的Java类,有对应的设置阈值的Java方法,java.lang.management.MemoryPoolMXBean.setUsageThreshold(long threshold)和setCollectionUsageThreshold(long threshold)方法,其中setUsageThreshold的方法实现如下:

二、MemoryManager

1、定义

      MemoryManager的定义位于hotspot src/shared/vm/service/memoryManager.hpp中,MemoryManager用来管理一个或者多个MemoryPool,垃圾回收器就是典型的MemoryManager。JVM有多个MemoryManager,一个MemoryPool可以被一个或者多个MemoryManager管理。MemoryManager定义的属性如下:

max_num_pools是一个枚举值,值是10,_memory_mgr_obj表示一个与之对应的Java对象。

MemoryManager的类继承关系如下:

   为了能够方便区分MemoryManager的类型,MemoryManager定义了一个kind方法,该方法返回一个枚举值MemoryManager::Name来表示MemoryManager的类型,其定义如下:

MemoryManager定义的方法比较简单,重点关注get_memory_manager_instance的实现。 

2、get_memory_manager_instance

     get_memory_manager_instance的用法同MemoryPool的get_memory_pool_instance方法,返回一个属性_memory_mgr_obj,如果为空则创建一个与之关联的Java对象,对应的Java类是java.lang.management.MemoryManagerMXBean或者java.lang.management.GarbageCollectorMXBean,该方法的源码说明如下:

instanceOop MemoryManager::get_memory_manager_instance(TRAPS) {
  //获取属性_memory_mgr_obj的最新值
  instanceOop mgr_obj = (instanceOop)OrderAccess::load_ptr_acquire(&_memory_mgr_obj);
  if (mgr_obj == NULL) {
    // 获取Java类sun_management_ManagementFactory
    Klass* k = Management::sun_management_ManagementFactory_klass(CHECK_0);
    instanceKlassHandle ik(THREAD, k);
    //创建当前MemoryManager的名字对应的String
    Handle mgr_name = java_lang_String::create_from_str(name(), CHECK_0);

    JavaValue result(T_OBJECT);
    JavaCallArguments args;
    //只有一个参数,MemoryManager的名字
    args.push_oop(mgr_name);    // Argument 1

    Symbol* method_name = NULL;
    Symbol* signature = NULL;
    //如果是gc_memory_manager,GCMemoryManager及其子类返回true,其他的返回false
    if (is_gc_memory_manager()) {
      //createGarbageCollector方法的方法名和方法签名
      method_name = vmSymbols::createGarbageCollector_name();
      signature = vmSymbols::createGarbageCollector_signature();
      //放一个空对象
      args.push_oop(Handle());      // Argument 2 (for future extension)
    } else {
      //createMemoryManager方法的方法名和签名
      method_name = vmSymbols::createMemoryManager_name();
      signature = vmSymbols::createMemoryManager_signature();
    }
    //调用Java方法
    JavaCalls::call_static(&result,
                           ik,
                           method_name,
                           signature,
                           &args,
                           CHECK_0);
    //获取调用结果
    instanceOop m = (instanceOop) result.get_jobject();
    instanceHandle mgr(THREAD, m);

    {
      //如果其他线程已经完成初始化
      mgr_obj = (instanceOop)OrderAccess::load_ptr_acquire(&_memory_mgr_obj);
      if (mgr_obj != NULL) {
         return mgr_obj;
      }
      //更新属性值
      mgr_obj = mgr();
      OrderAccess::release_store_ptr(&_memory_mgr_obj, mgr_obj);
    }
  }

  return mgr_obj;
}

调用的Java方法的如下图:

 get_memory_manager_instance的调用链如下:

最后一个GetMemoryManagers方法的调用链如下:

三、GCMemoryManager

1、定义

     CodeCacheMemoryManager和MetaspaceMemoryManager继承自MemoryManager,只是修改了kind和name方法的返回值而已,GCMemoryManager在 MemoryManager的基础上增加了部分跟GC相关的字段,如下:

  •   size_t       _num_collections;  //执行GC的总次数
  •   elapsedTimer _accumulated_timer;  //累积时间
  •   elapsedTimer _gc_timer;         // 当前GC的时间
  •   GCStatInfo*  _last_gc_stat;  //上一次GC的统计数据
  •   Mutex*       _last_gc_lock; //上一次GC的锁
  •   GCStatInfo*  _current_gc_stat;  //当前GC的统计数据
  •   int          _num_gc_threads;  //GC的线程数
  •   volatile bool _notification_enabled;   //是否允许通知GC的结果
  •   bool         _pool_always_affected_by_gc[MemoryManager::max_num_pools];  //标识管理的MemoryPool是否在GC完成后更新MemoryUsage

    GCMemoryManager定义的方法都是属性相关的,重点关注其中的gc_begin/gc_end方法的实现即可。

    GCStatInfo和 GCMemoryManager都位于memoryManager.hpp中,其定义的属性如下:

  •   size_t _index;    //当前第几次GC
  •   jlong  _start_time;  //gc开始时间
  •   jlong  _end_time;  //gc结束时间
  •   MemoryUsage* _before_gc_usage_array;  //是一个数组,通过index属性来读写数组的元素,每个元素对应一个MemoryPool,表示该Pool执行GC前的内存使用情况
  •   MemoryUsage* _after_gc_usage_array;  //同上,表示index处的MemoryPool在GC完成后的内存使用情况
  •   int          _usage_array_size;  //表示MemoryPool数组的长度,等于GCMemoryManager管理的MemoryPool的个数

  参考set_before_gc_usage方法的源码,如下:

 void set_before_gc_usage(int pool_index, MemoryUsage usage) {
    assert(pool_index >= 0 && pool_index < _usage_array_size, "Range checking");
    set_gc_usage(pool_index, usage, true /* before gc */);
  }

void GCStatInfo::set_gc_usage(int pool_index, MemoryUsage usage, bool before_gc) {
  MemoryUsage* gc_usage_array;
  if (before_gc) {
    gc_usage_array = _before_gc_usage_array;
  } else {
    gc_usage_array = _after_gc_usage_array;
  }
  gc_usage_array[pool_index] = usage;
}

 2、gc_begin/gc_end

     gc_begin方法用于在GC开始前记录MemoryPool的使用情况,gc_end用于在GC结束后记录MemoryPool的使用情况,两者的调用链如下:

    

即通过TraceMemoryManagerStats类的构造方法调用gc_begin,析构方法调用gc_end。这两方法的源码实现如下:

void GCMemoryManager::gc_begin(bool recordGCBeginTime, bool recordPreGCUsage,
                               bool recordAccumulatedGCTime) {
  assert(_last_gc_stat != NULL && _current_gc_stat != NULL, "Just checking");
  //如果统计累计GC时间
  if (recordAccumulatedGCTime) {
    _accumulated_timer.start();
  }
  //如果记录GC开始时间
  if (recordGCBeginTime) {
    _current_gc_stat->set_index(_num_collections+1);
    _current_gc_stat->set_start_time(Management::timestamp());
  }
   
  //如果在GC前记录内存使用情况
  if (recordPreGCUsage) {
    //遍历所有的MemoryPool
    for (int i = 0; i < MemoryService::num_memory_pools(); i++) {
      MemoryPool* pool = MemoryService::get_memory_pool(i);
      MemoryUsage usage = pool->get_memory_usage();
      //GC前的MemoryUsage
      _current_gc_stat->set_before_gc_usage(i, usage);
      //打印日志
      HS_DTRACE_PROBE8(hotspot, mem__pool__gc__begin,
        name(), strlen(name()),
        pool->name(), strlen(pool->name()),
        usage.init_size(), usage.used(),
        usage.committed(), usage.max_size());

    }
  }
}

//垃圾回收器因为某些原因终止了也要调用此方法
void GCMemoryManager::gc_end(bool recordPostGCUsage,
                             bool recordAccumulatedGCTime,
                             bool recordGCEndTime, bool countCollection,
                             GCCause::Cause cause,
                             bool allMemoryPoolsAffected) {
  //记录GC累计时间                           
  if (recordAccumulatedGCTime) {
    _accumulated_timer.stop();
  }
  //记录GC结束时间
  if (recordGCEndTime) {
    _current_gc_stat->set_end_time(Management::timestamp());
  }

  if (recordPostGCUsage) {
    int i;
    //遍历所有MemoryPool
    for (i = 0; i < MemoryService::num_memory_pools(); i++) {
      MemoryPool* pool = MemoryService::get_memory_pool(i);
      MemoryUsage usage = pool->get_memory_usage();
      //打印日志
      HS_DTRACE_PROBE8(hotspot, mem__pool__gc__end,
        name(), strlen(name()),
        pool->name(), strlen(pool->name()),
        usage.init_size(), usage.used(),
        usage.committed(), usage.max_size());
       //记录GC后的内存使用
      _current_gc_stat->set_after_gc_usage(i, usage);
    }

    //遍历所有MemoryPool
    for (i = 0; i < num_memory_pools(); i++) {
      MemoryPool* pool = get_memory_pool(i);
      MemoryUsage usage = pool->get_memory_usage();

      // Compare with GC usage threshold
      if (allMemoryPoolsAffected || pool_always_affected_by_gc(i)) {
        //更新GC后的内存使用情况
        pool->set_last_collection_usage(usage);
        //判断是否超过阈值,增加SensorInfo中的计数器
        LowMemoryDetector::detect_after_gc_memory(pool);
      }
    }
  }

  if (countCollection) {
    _num_collections++;
    //重置_last_gc_stat和_current_gc_stat
    {
      MutexLockerEx ml(_last_gc_lock, Mutex::_no_safepoint_check_flag);
      GCStatInfo *tmp = _last_gc_stat;
      _last_gc_stat = _current_gc_stat;
      _current_gc_stat = tmp;
      // reset the current stat for diagnosability purposes
      _current_gc_stat->clear();
    }

    if (is_notification_enabled()) {
      bool isMajorGC = this == MemoryService::get_major_gc_manager();
      //添加一个待发送的通知消息,该消息最终通过GCNotifier::sendNotificationInternal方法发送出去,
      //该方法最终调用sun_management_GarbageCollectorImpl类的createGCNotification方法
      GCNotifier::pushNotification(this, isMajorGC ? "end of major GC" : "end of minor GC",
                                   GCCause::to_string(cause));
    }
  }
}

3、GCNotifier pushNotification 和 sendNotificationInternal

     pushNotification用于创建一个GC通知消息,将其放入队列中;sendNotificationInternal用于从队列中获取并发送GC通知消息,由内部线程ServiceThread不断执行,这两方法的源码如下:

void GCNotifier::pushNotification(GCMemoryManager *mgr, const char *action, const char *cause) {
 
  int num_pools = MemoryService::num_memory_pools();
  //创建一个新的GCStatInfo
  GCStatInfo* stat = new(ResourceObj::C_HEAP, mtGC) GCStatInfo(num_pools);
  //将上一次GC的GCStatInfo复制到这个新的实例中
  mgr->get_last_gc_stat(stat);
  //创建一个新的GC通知
  GCNotificationRequest *request = new GCNotificationRequest(os::javaTimeMillis(),mgr,action,cause,stat);
  //添加到缓存队列中
  addRequest(request);
 }

void GCNotifier::addRequest(GCNotificationRequest *request) {
  //获取Service_lock
  MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag);
  if(first_request == NULL) {
    first_request = request;
  } else {
    last_request->next = request;
  }
  last_request = request;
  Service_lock->notify_all();
}

GCNotificationRequest *GCNotifier::getRequest() {
  MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag);
  GCNotificationRequest *request = first_request;
  //更新first_request,即按照添加的顺序依次处理
  if(first_request != NULL) {
    first_request = first_request->next;
  }
  return request;
}

void GCNotifier::sendNotificationInternal(TRAPS) {
  ResourceMark rm(THREAD);
  HandleMark hm(THREAD);
  //获取待发送的一个GC通知消息
  GCNotificationRequest *request = getRequest();
  if (request != NULL) {
    NotificationMark nm(request);
    //创建一个com_sun_management_GcInfo类实例
    Handle objGcInfo = createGcInfo(request->gcManager, request->gcStatInfo, CHECK);
    //初始化其他的方法参数
    Handle objName = java_lang_String::create_from_str(request->gcManager->name(), CHECK);
    Handle objAction = java_lang_String::create_from_str(request->gcAction, CHECK);
    Handle objCause = java_lang_String::create_from_str(request->gcCause, CHECK);

    Klass* k = Management::sun_management_GarbageCollectorImpl_klass(CHECK);
    instanceKlassHandle gc_mbean_klass(THREAD, k);

    instanceOop gc_mbean = request->gcManager->get_memory_manager_instance(THREAD);
    instanceHandle gc_mbean_h(THREAD, gc_mbean);
    //校验gc_mbean必须是sun_management_GarbageCollectorImpl实例
    if (!gc_mbean_h->is_a(k)) {
      THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
                "This GCMemoryManager doesn't have a GarbageCollectorMXBean");
    }

    JavaValue result(T_VOID);
    JavaCallArguments args(gc_mbean_h);
    //设置方法参数
    args.push_long(request->timestamp);
    args.push_oop(objName);
    args.push_oop(objAction);
    args.push_oop(objCause);
    args.push_oop(objGcInfo);
   
    //调用sun_management_GarbageCollectorImpl的createGCNotification方法
    JavaCalls::call_virtual(&result,
                            gc_mbean_klass,
                            vmSymbols::createGCNotification_name(),
                            vmSymbols::createGCNotification_signature(),
                            &args,
                            CHECK);
  }
}

同内存使用超过阈值的触发的消息,执行GC后发送的消息的监听也可通过javax.management.StandardEmitterMBean.addNotificationListener方法增加消息的监听逻辑。

sendNotificationInternal的调用链如下:

四、MemoryService 

     MemoryService定义在hotspot src/shared/vm/service/memoryService .hpp中,其定义的方法都是静态工具方法,提供MemoryPool和MemoryManager相关的统一入口方法。其定义的static属性如下:

  •   GrowableArray<MemoryPool*>*    _pools_list;  //所有的MemoryPool数组
  •   GrowableArray<MemoryManager*>* _managers_list;  //所有的MemoryManager数组
  •   GCMemoryManager*               _major_gc_manager;  //FullGC对应的GCMemoryManager
  •   GCMemoryManager*               _minor_gc_manager; //YoungGC对应的GCMemoryManager
  •   MemoryPool*                    _code_heap_pool;    
  •   MemoryPool*                    _metaspace_pool;
  •   MemoryPool*                    _compressed_class_pool;

重点关注以下方法的实现。 

 1、set_universe_heap

      set_universe_heap在是CollectedHeap初始化完成后调用的,用来设置CollectedHeap对应的MemoryPool和GCMemoryManager,其调用链如下:

其源码说明如下:

void MemoryService::set_universe_heap(CollectedHeap* heap) {
  CollectedHeap::Name kind = heap->kind();
  //区分不同的堆类型,分别处理
  switch (kind) {
    case CollectedHeap::GenCollectedHeap : {
      add_gen_collected_heap_info(GenCollectedHeap::heap());
      break;
    }
#if INCLUDE_ALL_GCS
    case CollectedHeap::ParallelScavengeHeap : {
      add_parallel_scavenge_heap_info(ParallelScavengeHeap::heap());
      break;
    }
    case CollectedHeap::G1CollectedHeap : {
      add_g1_heap_info(G1CollectedHeap::heap());
      break;
    }
#endif // INCLUDE_ALL_GCS
    default: {
      guarantee(false, "Unrecognized kind of heap");
    }
  }

  //会遍历所有的GC线程
  GcThreadCountClosure gctcc;
  heap->gc_threads_do(&gctcc);
  int count = gctcc.count();
  if (count > 0) {
    //设置GC线程数
    _minor_gc_manager->set_num_gc_threads(count);
    _major_gc_manager->set_num_gc_threads(count);
  }

  //初始化GCStatInfo
  _minor_gc_manager->initialize_gc_stat_info();
  _major_gc_manager->initialize_gc_stat_info();
}


void MemoryService::add_gen_collected_heap_info(GenCollectedHeap* heap) {
  CollectorPolicy* policy = heap->collector_policy();

  assert(policy->is_two_generation_policy(), "Only support two generations");
  guarantee(heap->n_gens() == 2, "Only support two-generation heap");

  TwoGenerationCollectorPolicy* two_gen_policy = policy->as_two_generation_policy();
  if (two_gen_policy != NULL) {
    GenerationSpec** specs = two_gen_policy->generations();
    Generation::Name kind = specs[0]->name();
    //区分不同的Generation设置_minor_gc_manager
    switch (kind) {
      case Generation::DefNew:
        _minor_gc_manager = MemoryManager::get_copy_memory_manager();
        break;
#if INCLUDE_ALL_GCS
      case Generation::ParNew:
      case Generation::ASParNew:
        _minor_gc_manager = MemoryManager::get_parnew_memory_manager();
        break;
#endif // INCLUDE_ALL_GCS
      default:
        guarantee(false, "Unrecognized generation spec");
        break;
    }
    //设置_major_gc_manager
    if (policy->is_mark_sweep_policy()) {
      _major_gc_manager = MemoryManager::get_msc_memory_manager();
#if INCLUDE_ALL_GCS
    } else if (policy->is_concurrent_mark_sweep_policy()) {
      _major_gc_manager = MemoryManager::get_cms_memory_manager();
#endif // INCLUDE_ALL_GCS
    } else {
      guarantee(false, "Unknown two-gen policy");
    }
  } else {
    guarantee(false, "Non two-gen policy");
  }
  //添加manager
  _managers_list->append(_minor_gc_manager);
  _managers_list->append(_major_gc_manager);
  //区分不同的Generation,为eden和survivor区分别创建适配的MemoryPool,并添加到_pools_list中
  //参考add_psYoung_memory_pool方法的实现
  add_generation_memory_pool(heap->get_gen(minor), _major_gc_manager, _minor_gc_manager);
  add_generation_memory_pool(heap->get_gen(major), _major_gc_manager);
}

void MemoryService::add_parallel_scavenge_heap_info(ParallelScavengeHeap* heap) {
  //设置对应的_minor_gc_manager和_major_gc_manager
  _minor_gc_manager = MemoryManager::get_psScavenge_memory_manager();
  _major_gc_manager = MemoryManager::get_psMarkSweep_memory_manager();
  _managers_list->append(_minor_gc_manager);
  _managers_list->append(_major_gc_manager);
  //为eden和survivor区分别创建适配的MemoryPool,并添加到_pools_list中
  add_psYoung_memory_pool(heap->young_gen(), _major_gc_manager, _minor_gc_manager);
  add_psOld_memory_pool(heap->old_gen(), _major_gc_manager);
}

void MemoryService::add_g1_heap_info(G1CollectedHeap* g1h) {
  assert(UseG1GC, "sanity");
 //设置对应的_minor_gc_manager和_major_gc_manager
  _minor_gc_manager = MemoryManager::get_g1YoungGen_memory_manager();
  _major_gc_manager = MemoryManager::get_g1OldGen_memory_manager();
  _managers_list->append(_minor_gc_manager);
  _managers_list->append(_major_gc_manager);
   //为eden和survivor区分别创建适配的MemoryPool,并添加到_pools_list中
  add_g1YoungGen_memory_pool(g1h, _major_gc_manager, _minor_gc_manager);
  add_g1OldGen_memory_pool(g1h, _major_gc_manager, _minor_gc_manager);
}

void MemoryService::add_psYoung_memory_pool(PSYoungGen* gen,
                                            GCMemoryManager* major_mgr,
                                            GCMemoryManager* minor_mgr) {
  assert(major_mgr != NULL && minor_mgr != NULL, "Should have two managers");

  // Add a memory pool for each space and young gen doesn't
  // support low memory detection as it is expected to get filled up.
  EdenMutableSpacePool* eden = new EdenMutableSpacePool(gen,
                                                        gen->eden_space(),
                                                        "PS Eden Space",
                                                        MemoryPool::Heap,
                                                        false /* support_usage_threshold */);

  SurvivorMutableSpacePool* survivor = new SurvivorMutableSpacePool(gen,
                                                                    "PS Survivor Space",
                                                                    MemoryPool::Heap,
                                                                    false /* support_usage_threshold */);

  major_mgr->add_pool(eden);
  major_mgr->add_pool(survivor);
  minor_mgr->add_pool(eden);
  minor_mgr->add_pool(survivor);
  _pools_list->append(eden);
  _pools_list->append(survivor);
}

 2、gc_begin /  gc_end

      gc_begin和gc_end方法是对GCMemoryManager的gc_begin和gc_end的再封装,其源码实现如下:

void MemoryService::gc_begin(bool fullGC, bool recordGCBeginTime,
                             bool recordAccumulatedGCTime,
                             bool recordPreGCUsage, bool recordPeakUsage) {

  GCMemoryManager* mgr;
  //根据是否fullGC找到对应的GCMemoryManager
  if (fullGC) {
    mgr = _major_gc_manager;
  } else {
    mgr = _minor_gc_manager;
  }
  assert(mgr->is_gc_memory_manager(), "Sanity check");
  //执行gc_begin
  mgr->gc_begin(recordGCBeginTime, recordPreGCUsage, recordAccumulatedGCTime);

  
  if (recordPeakUsage) {
    for (int i = 0; i < _pools_list->length(); i++) {
      MemoryPool* pool = _pools_list->at(i);
      //记录GC开始前的内存使用
      pool->record_peak_memory_usage();
    }
  }
}

void MemoryService::gc_end(bool fullGC, bool recordPostGCUsage,
                           bool recordAccumulatedGCTime,
                           bool recordGCEndTime, bool countCollection,
                           GCCause::Cause cause,
                           bool allMemoryPoolsAffected) {

  GCMemoryManager* mgr;
  if (fullGC) {
    mgr = (GCMemoryManager*) _major_gc_manager;
  } else {
    mgr = (GCMemoryManager*) _minor_gc_manager;
  }
  assert(mgr->is_gc_memory_manager(), "Sanity check");

  //GC完成,记录GC的耗时,GC后的内存使用情况等
  mgr->gc_end(recordPostGCUsage, recordAccumulatedGCTime, recordGCEndTime,
              countCollection, cause, allMemoryPoolsAffected);
}

void MemoryPool::record_peak_memory_usage() {
  // 将当前的内存使用的各项指标跟历史最大值比,取最大值
  MemoryUsage usage = get_memory_usage();
  size_t peak_used = get_max_value(usage.used(), _peak_usage.used());
  size_t peak_committed = get_max_value(usage.committed(), _peak_usage.committed());
  size_t peak_max_size = get_max_value(usage.max_size(), _peak_usage.max_size());
   //创建新的MemoryUsage
  _peak_usage = MemoryUsage(initial_size(), peak_used, peak_committed, peak_max_size);
}

 上述方法涉及了垃圾回收相关的多个数据结构,这些类的具体用法后面的博客会详细介绍,此处只是了解一个整体的轮廓。

发布了117 篇原创文章 · 获赞 8 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_31865983/article/details/103447049