文档章节

关于【JVM Performance Counters】的实现

tivenwang
 tivenwang
发布于 2016/12/10 14:18
字数 1076
阅读 37
收藏 0
点赞 0
评论 0

    在Java内置工具包tools.jar(一)sun.tools.jstack.Jps中我们谈到,jps工具的数据来源自hsperfdata_xxx目录下的文件中。其实,除了jps还有jstat以及基于此命令之上提供的jstatd、visualgc工具,数据来源均基于JVM Performance Counters输出的文件中,在JVM中该文件被称为PerfData。PerfData中记录了JVM运行时刻gc、编译器、classLoder、操作系统、线程等的状态数据,对于分析jvm运行状态非常重要。
      从头开始,在JVM初始化函数中,我们看到初始化全局数据中执行了perfMemory_init()方法:

void vm_init_globals() {
  check_ThreadShadow();
  basic_types_init();
  eventlog_init();
  mutex_init();
  chunkpool_init();
  perfMemory_init();
}
void perfMemory_init() {
  if (!UsePerfData) return;
  PerfMemory::initialize();
}
// create the PerfData memory region
//
// This method creates the memory region used to store performance
// data for the JVM. The memory may be created in standard or
// shared memory.
//
void PerfMemory::create_memory_region(size_t size) {

  if (PerfDisableSharedMem) {
    // do not share the memory for the performance data.
    _start = create_standard_memory(size);
  }
  else {
    _start = create_shared_memory(size);
    if (_start == NULL) {

      // creation of the shared memory region failed, attempt
      // to create a contiguous, non-shared memory region instead.
      //
      if (PrintMiscellaneous && Verbose) {
        warning("Reverting to non-shared PerfMemory region.\n");
      }
      PerfDisableSharedMem = true;
      _start = create_standard_memory(size);
    }
  }

  if (_start != NULL) _capacity = size;
}

也就是PerfData的初始化,其中UsePerfData控制了是否使用该特性。

-XX:+UsePerfData:Enables the perfdata feature. This option is enabled by default to allow JVM monitoring and performance testing. Disabling it suppresses the creation of the hsperfdata_userid directories. To disable the perfdata feature, specify -XX:-UsePerfData.

PerfMemory的初始化在不同的操作系统有不同的实现,我们仍以Linux为例,jvm需要申请一份内存在存储这份数据,从代码中可以看到我们有两种选择:create_shared_memory 和create_standard_memory,共享模式的内存即使用文件hsperfdata_xxx来给不同的用户/进程来读取,该文件同时使用mmap的方式将内容映射到内存中。私有模式即申请普通内存,此时外部进程无法读取内存数据,所以基于此数据的命令都将失效(jps/jstat等),另外需要注意的是在共享模式申请内存(同时可以理解为创建文件)失败时会转换为私有模式。这里又来了一个JVM参数PerfDisableSharedMem,默认我们使用的jdk都是false使用共享模式,但我们仍可以使用参数来控制这个行为。

product(bool, PerfDisableSharedMem, false,"Store performance data in standard memory")

        那么,存储性能数据的内存空间已经申请完毕,接下来如何收集数据?Performance Counters定义了一些它数据来源的nameSpace,如下代码所示。

/* jvmstat global and subsystem counter name space - enumeration value
 * serve as an index into the PerfDataManager::_name_space[] array
 * containing the corresponding name space string. Only the top level
 * subsystem name spaces are represented here.
 */
enum CounterNS {
  // top level name spaces
  JAVA_NS,
  COM_NS,
  SUN_NS,
  // subsystem name spaces
  JAVA_GC,              // Garbage Collection name spaces
  COM_GC,
  SUN_GC,
  JAVA_CI,              // Compiler name spaces
  COM_CI,
  SUN_CI,
  JAVA_CLS,             // Class Loader name spaces
  COM_CLS,
  SUN_CLS,
  JAVA_RT,              // Runtime name spaces
  COM_RT,
  SUN_RT,
  JAVA_OS,              // Operating System name spaces
  COM_OS,
  SUN_OS,
  JAVA_THREADS,         // Threads System name spaces
  COM_THREADS,
  SUN_THREADS,
  JAVA_PROPERTY,        // Java Property name spaces
  COM_PROPERTY,
  SUN_PROPERTY,
  NULL_NS,
  COUNTERNS_LAST = NULL_NS
};

在JVM运行期间,通过调用PerfDataManager保持时刻记录这些运行数据,它提供一系列的接口供收集性能数据,我们以查找调用方的方式可以看到StatSampler是触发数据收集的函数,它在Thread::create_vm()时创建的一个守护线程,在engage()中看到它的初始化伴随一个JVM参数PerfDataSamplingInterval:默认50秒执行一次去counter数据。

product(intx, PerfDataSamplingInterval, 50 /*ms*/,"Data sampling interval in milliseconds")

至此,性能数据就源源不断的采集下来,我们回顾一下整个流程:

1、启动jvm,初始化perfData内存。包含共享内存和普通内存申请。共享内存涉及映射文件的创建位置等逻辑。
2、一个线程启动,均会初始化StatSampler,以PerfDataSamplingInterval的频率采集数据至perfData中。
3、perfData汇总数据存储在内存中,在共享内存模式下以mmap方式映射到文件中。
4、文件可被其他进程/用户读取。

以数据流的方式来理解,其实并没有什么高深之处,数据的收集需要各个运行模块配合采集。这样就完成了Performance Counters的功能,这些数据能够在我们排查性能问题、处理故障时发挥巨大作用。

© 著作权归作者所有

共有 人打赏支持
tivenwang
粉丝 1
博文 12
码字总数 13424
作品 0
浦东
程序员
Java学习---Java简单认识

前言 小编在学习Java方面的基础知识,发现里面有很多是结合之前的语言的特点发展过来的,不同的地方是,Java有它自己的发展和特点。下面小编先简单地做一下总结,结合看过的1-2章的J2SE视频,...

m18633778874 ⋅ 04/01 ⋅ 0

JDK 11 特性抢先看:5 月新增三个 JEP

一周前(2018年5月7日),JDK11 新增了三个 JEP 。在 jdk-dev 邮件列表中出现了三封邮件,Mark Reinhold 发表了以下公告: JDK 11 实现了 JEP:324:关于 Curve25519 和 Curve448 的重要协议...

oschina ⋅ 05/16 ⋅ 0

ThreadLocal源码分析

阅读原文请访问我的博客 BrightLoong's Blog 一. 简介 提醒篇幅较大需耐心。 简介来自ThreadLocal类注释 ThreadLocal类提供了线程局部 (thread-local) 变量。这些变量与普通变量不同,每个线...

BrightLoong ⋅ 05/28 ⋅ 0

《成神之路-基础篇》JVM——垃圾回收(已完结)

Java内存模型,Java内存管理,Java堆和栈,垃圾回收 本文是[《成神之路系列文章》][1]的第一篇,主要是关于JVM的一些介绍。 持续更新中 Java之美[从菜鸟到高手演变]之JVM内存管理及垃圾回收 ...

⋅ 05/05 ⋅ 0

深入理解 ThreadLocal (这些细节不应忽略)

前言 对于 ThreadLocal 的使用,并不难。但要深入理解 ThreadLocal 的实现方式,需要细细揣摩。写本文前,我在网上看了很多关于 ThreadLocal 的分析,但却感到遗憾,因为很多文章存在着一定误...

徐志毅 ⋅ 04/11 ⋅ 0

2018年Java编程学习面试最全知识点总结

Java是一种可以撰写跨平台应用软件的面向对象的程序设计语言。Java 技术具有卓越的通用性、高效性、平台移植性和安全性,广泛应用于PC、数据中心、游戏控制台、科学超级计算机、移动电话和互...

Java小辰 ⋅ 05/14 ⋅ 0

Java 使用 happen-before 规则实现共享变量的同步操作

前言 熟悉 Java 并发编程的都知道,JMM(Java 内存模型) 中的 happen-before(简称 hb)规则,该规则定义了 Java 多线程操作的有序性和可见性,防止了编译器重排序对程序结果的影响。按照官方的...

stateIs0 ⋅ 01/20 ⋅ 0

Android JNI(一)——NDK与JNI基础

本系列文章如下: Android JNI(一)——NDK与JNI基础 Android JNI学习(二)——实战JNI之“hello world” Android JNI学习(三)——Java与Native相互调用 Android JNI学习(四)——JNI的常用方法...

隔壁老李头 ⋅ 05/09 ⋅ 0

Spring之jdbc Template实现CRUD操作

Spring为各种持久化技术都提供了简单操作的模板回调。比如jdbc、hibernate、Mybatis以及JPA等。 这里我们就以JDBC为例,看看JDBC template怎么实现CRUD操作。 JdbcTemplate主要提供以下几类方...

Java攻城玩家 ⋅ 05/31 ⋅ 0

ThreadLocal趣谈 —— 杨过和他的四个冤家

一个一个上 一日醒来,杨过发现小龙女离家出走,于是外出寻找,不料碰上了金轮法王、李莫愁、裘千尺、公孙止四个冤家。 “哼,四个打我一个,算什么英雄好汉,有本事的,一个一个上!” 按照...

SexyCode ⋅ 06/12 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

知乎Java数据结构

作者:匿名用户 链接:https://www.zhihu.com/question/35947829/answer/66113038 来源:知乎 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 感觉知乎上嘲讽题主简...

颖伙虫 ⋅ 今天 ⋅ 0

Confluence 6 恢复一个站点有关使用站点导出为备份的说明

推荐使用生产备份策略。我们推荐你针对你的生产环境中使用的 Confluence 参考 Production Backup Strategy 页面中的内容进行备份和恢复(这个需要你备份你的数据库和 home 目录)。XML 导出备...

honeymose ⋅ 今天 ⋅ 0

JavaScript零基础入门——(九)JavaScript的函数

JavaScript零基础入门——(九)JavaScript的函数 欢迎回到我们的JavaScript零基础入门,上一节课我们了解了有关JS中数组的相关知识点,不知道大家有没有自己去敲一敲,消化一下?这一节课,...

JandenMa ⋅ 今天 ⋅ 0

火狐浏览器各版本下载及插件httprequest

各版本下载地址:http://ftp.mozilla.org/pub/mozilla.org//firefox/releases/ httprequest插件截至57版本可用

xiaoge2016 ⋅ 今天 ⋅ 0

Docker系列教程28-实战:使用Docker Compose运行ELK

原文:http://www.itmuch.com/docker/28-docker-compose-in-action-elk/,转载请说明出处。 ElasticSearch【存储】 Logtash【日志聚合器】 Kibana【界面】 答案: version: '2'services: ...

周立_ITMuch ⋅ 今天 ⋅ 0

使用快嘉sdkg极速搭建接口模拟系统

在具体项目研发过程中,一旦前后端双方约定好接口,前端和app同事就会希望后台同事可以尽快提供可供对接的接口方便调试,而对后台同事来说定好接口还仅是个开始、设计流程,实现业务逻辑,编...

fastjrun ⋅ 今天 ⋅ 0

PXE/KickStart 无人值守安装

导言 作为中小公司的运维,经常会遇到一些机械式的重复工作,例如:有时公司同时上线几十甚至上百台服务器,而且需要我们在短时间内完成系统安装。 常规的办法有什么? 光盘安装系统 ===> 一...

kangvcar ⋅ 昨天 ⋅ 0

使用Puppeteer撸一个爬虫

Puppeteer是什么 puppeteer是谷歌chrome团队官方开发的一个无界面(Headless)chrome工具。Chrome Headless将成为web应用自动化测试的行业标杆。所以我们很有必要来了解一下它。所谓的无头浏...

小草先森 ⋅ 昨天 ⋅ 0

Java Done Right

* 表示难度较大或理论性较强。 ** 表示难度更大或理论性更强。 【Java语言本身】 基础语法,面向对象,顺序编程,并发编程,网络编程,泛型,注解,lambda(Java8),module(Java9),var(...

风华神使 ⋅ 昨天 ⋅ 0

Linux系统日志

linux 系统日志 /var/log/messages /etc/logrotate.conf 日志切割配置文件 https://my.oschina.net/u/2000675/blog/908189 logrotate 使用详解 dmesg 命令 /var/log/dmesg 日志 last命令,调......

Linux学习笔记 ⋅ 昨天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部