栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

CompressedClassSpace和metaspace指标关系

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

CompressedClassSpace和metaspace指标关系

当我们打开jconsole查看数据的时候,会发现下面两处数据。

  1. memorypool里metaspace和compressed class space是并列的。
  2. noheap里也专门分了两个柱状图。

这里就有一个疑问了CompressedClassSpace是不是和metaspace的指标是包含关系?

找出指标暴露类

我们通过mbean的类信息查找到对应数据读取。下面是获取使用的代码。

JNIEXPORT jobject JNICALL
Java_sun_management_MemoryPoolImpl_getUsage0
  (JNIEnv *env, jobject pool)
{
    jobject usage = jmm_interface->GetMemoryPoolUsage(env, pool);
    if (usage == NULL) {
 // Throw internal error since this implementation expects the
 // pool will never become invalid.
 JNU_ThrowInternalError(env, "Memory Pool not found");
    }
    return usage;
}

可以看出具体的指标获取在GetMemoryPoolUsage中实现。通过这个方法点击进入只能看到接口,并没有实现。这里的GetMemoryPoolUsage是通过宏定义实现的,需要全文检索来找到实现的位置。

// Returns a java/lang/management/MemoryUsage object containing the memory usage
// of a given memory pool.
JVM_ENTRY(jobject, jmm_GetMemoryPoolUsage(JNIEnv* env, jobject obj))
  ResourceMark rm(THREAD);

  MemoryPool* pool = get_memory_pool_from_jobject(obj, CHECK_NULL);
  if (pool != NULL) {
    MemoryUsage usage = pool->get_memory_usage();
    Handle h = MemoryService::create_MemoryUsage_obj(usage, CHECK_NULL);
    return JNIHandles::make_local(env, h());
  } else {
    return NULL;
  }
JVM_END

在get_memory_pool_from_jobject中是可以根据我们的obj来获取到对应的MemoryPool。再往下就会追踪到如下的代码(中间省略其余的方法调用过程)。

MemoryPool* MemoryService::get_memory_pool(instanceHandle ph) {
  for (int i = 0; i < _pools_list->length(); i++) {
    MemoryPool* pool = _pools_list->at(i);
    if (pool->is_pool(ph)) {
      return pool;
    }
  }
  return NULL;
}

我们可以看到,获取的操作就在_pools_list中遍历比较获得。那我们根据_pools_list来找加入的地方就可以找到数据来源了。


void MemoryService::add_metaspace_memory_pools() {
  MemoryManager* mgr = MemoryManager::get_metaspace_memory_manager();
  _metaspace_pool = new metaspacePool();
  mgr->add_pool(_metaspace_pool);
  _pools_list->append(_metaspace_pool);
  if (UseCompressedClassPointers) {
    _compressed_class_pool = new CompressedKlassSpacePool();
    mgr->add_pool(_compressed_class_pool);
    _pools_list->append(_compressed_class_pool);
  }

  _managers_list->append(mgr);
}

metaspace的加入方法中会根据是否开启了指针压缩来增加_compressed_class_pool。

查看指标的数据来源

接下来我们来看看这两个pool的数据获取过程。

已使用指标

先看_compressed_class_pool,他的used的数据是通过获取metaspace中的class信息的数据。

size_t CompressedKlassSpacePool::used_in_bytes() {
  return metaspaceUtils::used_bytes(metaspace::ClassType);
}
static size_t used_bytes(metaspace::metadataType mdtype) {
  return used_words(mdtype) * BytesPerWord;
}

我们再看metaspacePool的获取。他获取是NonClassType和ClassType的总和。

size_t metaspacePool::used_in_bytes() {
  return metaspaceUtils::used_bytes();
}
static size_t used_bytes() {
  return used_words() * BytesPerWord;
}
static size_t used_words() {
  return used_words(metaspace::NonClassType) +
  used_words(metaspace::ClassType);
}

所以在使用量的指标上,metaspace中是包含了compressed class的部分的。

最大值指标

最大值的指标是通过指标类的构造参数传入的

CompressedKlassSpacePool::CompressedKlassSpacePool() :
  MemoryPool("Compressed Class Space", NonHeap, 0, CompressedClassSpaceSize, true, false) { }

compressed class是取的CompressedClassSpaceSize的值。这个值可以通过-XX:CompressedClassSpaceSize控制。但同时也受到其他参数影响。

  size_t min_metaspace_sz =
      VIRTUALSPACEMULTIPLIER * InitialBootClassLoadermetaspaceSize;
  if (UseCompressedClassPointers) {
    if ((min_metaspace_sz + CompressedClassSpaceSize) >  MaxmetaspaceSize) {
      if (min_metaspace_sz >= MaxmetaspaceSize) {
 vm_exit_during_initialization("MaxmetaspaceSize is too small.");
      } else {
 FLAG_SET_ERGO(size_t, CompressedClassSpaceSize,
 MaxmetaspaceSize - min_metaspace_sz);
      }
    }
  } else if (min_metaspace_sz >= MaxmetaspaceSize) {
    FLAG_SET_ERGO(size_t, InitialBootClassLoadermetaspaceSize,
    min_metaspace_sz);
  }

通过上面的代码,我们可以看到当min_metaspace_sz 加CompressedClassSpaceSize大于 MaxmetaspaceSize的时候,CompressedClassSpaceSize就强制被设置为(MaxmetaspaceSize - min_metaspace_sz)。
min_metaspace_sz是VIRTUALSPACEMULTIPLIER * InitialBootClassLoadermetaspaceSize的乘积。VIRTUALSPACEMULTIPLIER是个宏是2,InitialBootClassLoadermetaspaceSize是根据-XX:InitialBootClassLoadermetaspaceSize的参数设置的。
CompressedClassSpaceSize是MaxmetaspaceSize,InitialBootClassLoadermetaspaceSize,CompressedClassSpaceSize这三个参数共同影响的结果。
metaspace的最大值就比较简单。

metaspacePool::metaspacePool() :
  MemoryPool("metaspace", NonHeap, 0, calculate_max_size(), true, false) { }
 size_t metaspacePool::calculate_max_size() const {
  return FLAG_IS_CMDLINE(MaxmetaspaceSize) ? MaxmetaspaceSize :
   MemoryUsage::undefined_size();
}
 static size_t undefined_size() { return (size_t) -1; }

最大值就是获取的MaxmetaspaceSize的值,如果这个值没有设置,那就是-1。这里也有一个注意的点。

  if (metaspaceSize > MaxmetaspaceSize) {
    metaspaceSize = MaxmetaspaceSize;
  }

当metaspaceSize的值超过MaxmetaspaceSize的时候,会拿MaxmetaspaceSize的赋值给metaspaceSize。启动不会报错,所以一直是以MaxmetaspaceSize为最大值。

小结
  1. jmx的metaspace的使用值是包括了CompressedClassSpace的。
  2. CompressedClassSpace的最大值是MaxmetaspaceSize,InitialBootClassLoadermetaspaceSize,CompressedClassSpaceSize这三个参数共同影响的结果。
  3. MaxmetaspaceSize是唯一最大限制,不会受到metaspaceSize的干扰。
转载请注明:文章转载自 www.mshxw.com
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号