为了账号安全,请及时绑定邮箱和手机立即绑定

jmx的gc指标数据是如何获取的

标签:
Java

jmx会暴露进程开始运行后的gc总次数和gc总时间。这个数据究竟是怎么获取的。下面以ps为例。我们来查看一下流程。

              for (GarbageCollectorMXBean garbageCollectorMBean : garbageCollectors) {
                    String gcName = garbageCollectorMBean.getName();
                    long gcCount = garbageCollectorMBean.getCollectionCount();
                 
                }

java层面的api就是这一个样子,可以从mbean众读取gc的次数。
我们从接口找到实现类。发现这是一个native的方法。

public class GarbageCollectorImpl extends MemoryManagerImpl
    implements GarbageCollectorMXBean {

    protected GarbageCollectorImpl(String name) {
        super(name);
    }

    @Override
    public native long getCollectionCount();

根据jni的规则。我们找到具体的c实现。

JNIEXPORT jlong JNICALL Java_sun_management_GarbageCollectorImpl_getCollectionCount
  (JNIEnv *env, jobject mgr) {
    return jmm_interface->GetLongAttribute(env, mgr, JMM_GC_COUNT);
}

这里的JMM_GC_COUNT是个枚举。

static jlong get_gc_attribute(GCMemoryManager* mgr, jmmLongAttribute att) {
  switch (att) {
  case JMM_GC_TIME_MS:
    return mgr->gc_time_ms();

  case JMM_GC_COUNT:
    return mgr->gc_count();

  case JMM_GC_EXT_ATTRIBUTE_INFO_SIZE:
    // current implementation only has 1 ext attribute
    return 1;

  default:
    assert(0, "Unrecognized GC attribute");
    return -1;
  }
}

  size_t gc_count()                     { return _num_collections; }

在实现的代码里,我们可以看到数据是直接从mgr的gc_count中获取的。gc_count是直接获取的一个成员变量_num_collections。

void GCMemoryManager::gc_end(bool recordPostGCUsage,
                             bool recordAccumulatedGCTime,
                             bool recordGCEndTime, bool countCollection,
                             GCCause::Cause cause,
                             bool allMemoryPoolsAffected) {
                             …………
                               _num_collections++;

GCMemoryManager的gc_end。在MemoryService中被调用到。

void MemoryService::gc_end(GCMemoryManager* manager, bool recordPostGCUsage,
                           bool recordAccumulatedGCTime,
                           bool recordGCEndTime, bool countCollection,
                           GCCause::Cause cause,
                           bool allMemoryPoolsAffected) {
  manager->gc_end(recordPostGCUsage, recordAccumulatedGCTime, recordGCEndTime,
                  countCollection, cause, allMemoryPoolsAffected);
}

MemoryService在TraceMemoryManagerStats的析构函数里被调用。

TraceMemoryManagerStats::~TraceMemoryManagerStats() {
  MemoryService::gc_end(_gc_memory_manager, _recordPostGCUsage, _recordAccumulatedGCTime,
                        _recordGCEndTime, _countCollection, _cause, _allMemoryPoolsAffected);
}

jvm很多的计数方式都是通过析构函数做的。TraceMemoryManagerStats就是我们需要找的对象。
TraceMemoryManagerStats分散在每个gc的实现里。下面是PSParallelCompact的部分

    TraceMemoryManagerStats tms(heap->old_gc_manager(), gc_cause);

这里的调用为了能准确的析构,专门把gc的代码放在了一个代码块里。通过声明周期的控制,达到跟踪数据的目的。

后面还有很多计数也在这里的code里。例如gclog

void PSOldGen::print_used_change(size_t prev_used) const {
  log_info(gc, heap)("%s: "  SIZE_FORMAT "K->" SIZE_FORMAT "K("  SIZE_FORMAT "K)",
      name(), prev_used / K, used_in_bytes() / K, capacity_in_bytes() / K);
}

还有jstat的值的变化

void ParallelScavengeHeap::update_counters() {
  young_gen()->update_counters();
  old_gen()->update_counters();
  MetaspaceCounters::update_performance_counters();
  CompressedClassSpaceCounters::update_performance_counters();
}

nmt的变化

    // Track memory usage and detect low memory
    MemoryService::track_memory_usage();
点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消